"new_debug_unreachable",
]
+[[package]]
+name = "fxhash"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
+dependencies = [
+ "byteorder",
+]
+
[[package]]
name = "generic-array"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
[[package]]
name = "hostname"
version = "0.3.1"
"hashbrown",
]
+[[package]]
+name = "instructions-template"
+version = "0.1.0"
+dependencies = [
+ "indexmap",
+ "proc-macro2 1.0.32",
+ "quote 1.0.10",
+ "strum",
+ "strum_macros",
+ "syn 1.0.81",
+ "to-syn-value",
+ "to-syn-value_derive",
+]
+
[[package]]
name = "iovec"
version = "0.1.4"
"libc",
]
+[[package]]
+name = "rustversion"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
+
[[package]]
name = "rustyline"
version = "9.0.0"
"crossterm",
"dirs-next",
"divrem",
+ "fxhash",
"git-version",
"hostname",
"indexmap",
+ "instructions-template",
"lazy_static",
"lexical",
"libc",
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
+[[package]]
+name = "strum"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb"
+
+[[package]]
+name = "strum_macros"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38"
+dependencies = [
+ "heck",
+ "proc-macro2 1.0.32",
+ "quote 1.0.10",
+ "rustversion",
+ "syn 1.0.81",
+]
+
[[package]]
name = "subtle"
version = "1.0.0"
"winapi 0.3.9",
]
+[[package]]
+name = "to-syn-value"
+version = "0.1.0"
+dependencies = [
+ "syn 1.0.81",
+ "to-syn-value_derive",
+]
+
+[[package]]
+name = "to-syn-value_derive"
+version = "0.1.0"
+dependencies = [
+ "proc-macro2 1.0.32",
+ "quote 1.0.10",
+ "syn 1.0.81",
+]
+
[[package]]
name = "typenum"
version = "1.14.0"
build = "build.rs"
[workspace]
-members = ["crates/num-rug-adapter", "crates/static-string-indexing"]
+members = ["crates/num-rug-adapter",
+ "crates/static-string-indexing",
+ "crates/instructions-template",
+ "crates/to-syn-value",
+ "crates/to-syn-value_derive"]
[features]
num = ["num-rug-adapter"]
[build-dependencies]
indexmap = "1.0.2"
static-string-indexing = { path = "./crates/static-string-indexing" }
+instructions-template = { path = "./crates/instructions-template" }
proc-macro2 = "*"
[dependencies]
crossterm = "0.16.0"
dirs-next = "2.0.0"
divrem = "0.1.0"
+fxhash = "0.2.1"
git-version = "0.3.4"
hostname = "0.3.1"
indexmap = "1.0.2"
lazy_static = "1.4.0"
lexical = "5.2.2"
libc = "0.2.62"
-# temporary to remove unnecessary braces warnings.
modular-bitfield = { git = "https://github.com/mthom/modular-bitfield" } # modular-bitfield = "0.11.2"
nix = "0.15.0"
num-rug-adapter = { optional = true, path = "./crates/num-rug-adapter" }
use static_string_indexing::index_static_strings;
+use instructions_template::generate_instructions_rs;
use std::env;
use std::fs;
find_prolog_files(&mut libraries, "", &lib_path);
libraries.write_all(b"\n m\n };\n}\n").unwrap();
+ let instructions_path = Path::new("src/instructions.rs");
+ let mut instructions_file = File::create(&instructions_path).unwrap();
+
+ let quoted_output = generate_instructions_rs();
+
+ instructions_file
+ .write_all(quoted_output.to_string().as_bytes())
+ .unwrap();
+
+ Command::new("rustfmt")
+ .arg(instructions_path.as_os_str())
+ .spawn().unwrap()
+ .wait().unwrap();
+
let static_atoms_path = Path::new("src/static_atoms.rs");
let mut static_atoms_file = File::create(&static_atoms_path).unwrap();
--- /dev/null
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "hashbrown"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+
+[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "indexmap"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
+name = "instructions-template"
+version = "0.1.0"
+dependencies = [
+ "indexmap",
+ "proc-macro2",
+ "quote",
+ "strum",
+ "strum_macros",
+ "syn",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "392a54546fda6b7cc663379d0e6ce8b324cf88aecc5a499838e1be9781bdce2e"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
+
+[[package]]
+name = "strum"
+version = "0.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb"
+
+[[package]]
+name = "strum_macros"
+version = "0.23.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5bb0dc7ee9c15cea6199cde9a127fa16a4c5819af85395457ad72d68edc85a38"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecb2e6da8ee5eb9a61068762a32fa9619cc591ceb055b3687f4cd4051ec2e06b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "to-syn-value"
+version = "0.1.0"
+dependencies = [
+ "syn",
+ "to-syn-value_derive",
+]
+
+[[package]]
+name = "to-syn-value_derive"
+version = "0.1.0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
--- /dev/null
+[package]
+name = "instructions-template"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+indexmap = "*"
+proc-macro2 = "*"
+quote = "*"
+strum = "0.23"
+strum_macros = "0.23"
+syn = { version = "*", features = ['full', 'visit', 'extra-traits'] }
+to-syn-value = { path = "../to-syn-value" }
+to-syn-value_derive = { path = "../to-syn-value_derive" }
\ No newline at end of file
--- /dev/null
+// use crate::atom_table::*;
+// use crate::machine::machine_indices::*;
+// use crate::types::*;
+//
+
+use proc_macro2::TokenStream;
+use quote::{format_ident, quote, ToTokens, TokenStreamExt};
+use strum_macros::{EnumDiscriminants, EnumProperty, EnumString};
+use syn::*;
+use to_syn_value_derive::ToDeriveInput;
+
+/*
+ * 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
+ * Line instruction type. The strum crate is used to provide reflection
+ * on each of the node types to the tree walker.
+ */
+
+use std::any::*;
+use std::str::FromStr;
+
+struct ArithmeticTerm;
+struct Atom;
+struct CodeIndex;
+struct Death;
+struct HeapCellValue;
+struct IndexingLine;
+struct Level;
+struct NextOrFail;
+struct RegType;
+
+#[allow(dead_code)]
+#[derive(ToDeriveInput, EnumDiscriminants)]
+#[strum_discriminants(derive(EnumProperty, EnumString))]
+enum CompareNumber {
+ #[strum_discriminants(strum(props(Arity = "2", Name = ">")))]
+ NumberGreaterThan(ArithmeticTerm, ArithmeticTerm),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "<")))]
+ NumberLessThan(ArithmeticTerm, ArithmeticTerm),
+ #[strum_discriminants(strum(props(Arity = "2", Name = ">=")))]
+ NumberGreaterThanOrEqual(ArithmeticTerm, ArithmeticTerm),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "=<")))]
+ NumberLessThanOrEqual(ArithmeticTerm, ArithmeticTerm),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "=\\=")))]
+ NumberNotEqual(ArithmeticTerm, ArithmeticTerm),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "=:=")))]
+ NumberEqual(ArithmeticTerm, ArithmeticTerm),
+}
+
+#[allow(dead_code)]
+#[derive(ToDeriveInput, EnumDiscriminants)]
+#[strum_discriminants(derive(EnumProperty, EnumString))]
+enum CompareTerm {
+ #[strum_discriminants(strum(props(Arity = "2", Name = "@<")))]
+ TermLessThan,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "@=<")))]
+ TermLessThanOrEqual,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "@>=")))]
+ TermGreaterThanOrEqual,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "@>")))]
+ TermGreaterThan,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "==")))]
+ TermEqual,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "\\==")))]
+ TermNotEqual,
+}
+
+#[allow(dead_code)]
+#[derive(ToDeriveInput, EnumDiscriminants)]
+#[strum_discriminants(derive(EnumProperty, EnumString))]
+enum ClauseType {
+ BuiltIn(BuiltInClauseType),
+ #[strum_discriminants(strum(props(Arity = "arity", Name = "$call")))]
+ CallN(usize),
+ Inlined(InlinedClauseType),
+ #[strum_discriminants(strum(props(Arity = "arity", Name = "call_named")))]
+ Named(usize, Atom, CodeIndex), // name, arity, index.
+ System(SystemClauseType),
+}
+
+#[allow(dead_code)]
+#[derive(ToDeriveInput, EnumDiscriminants)]
+#[strum_discriminants(derive(EnumProperty, EnumString))]
+enum BuiltInClauseType {
+ #[strum_discriminants(strum(props(Arity = "1", Name = "acyclic_term")))]
+ AcyclicTerm,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "arg")))]
+ Arg,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "compare")))]
+ Compare,
+ CompareTerm(CompareTerm),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "copy_term")))]
+ CopyTerm,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "functor")))]
+ Functor,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "ground")))]
+ Ground,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "is")))]
+ Is(RegType, ArithmeticTerm),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "keysort")))]
+ KeySort,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "read")))]
+ Read,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "sort")))]
+ Sort,
+}
+
+#[allow(dead_code)]
+#[derive(ToDeriveInput, EnumDiscriminants)]
+#[strum_discriminants(derive(EnumProperty, EnumString))]
+enum InlinedClauseType {
+ CompareNumber(CompareNumber),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "atom")))]
+ IsAtom(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "atomic")))]
+ IsAtomic(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "compound")))]
+ IsCompound(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "integer")))]
+ IsInteger(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "number")))]
+ IsNumber(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "rational")))]
+ IsRational(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "float")))]
+ IsFloat(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "nonvar")))]
+ IsNonVar(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "var")))]
+ IsVar(RegType),
+}
+
+#[allow(dead_code)]
+#[derive(ToDeriveInput, EnumDiscriminants)]
+#[strum_discriminants(derive(EnumProperty, EnumString))]
+enum REPLCodePtr {
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$add_discontiguous_predicate")))]
+ AddDiscontiguousPredicate,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$add_dynamic_predicate")))]
+ AddDynamicPredicate,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$add_multifile_predicate")))]
+ AddMultifilePredicate,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$add_goal_expansion_clause")))]
+ AddGoalExpansionClause,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$add_term_expansion_clause")))]
+ AddTermExpansionClause,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$add_in_situ_filename_module")))]
+ AddInSituFilenameModule,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$clause_to_evacuable")))]
+ ClauseToEvacuable,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$scoped_clause_to_evacuable")))]
+ ScopedClauseToEvacuable,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$conclude_load")))]
+ ConcludeLoad,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$declare_module")))]
+ DeclareModule,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$load_compiled_library")))]
+ LoadCompiledLibrary,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$prolog_lc_source")))]
+ LoadContextSource,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$prolog_lc_file")))]
+ LoadContextFile,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$prolog_lc_dir")))]
+ LoadContextDirectory,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$prolog_lc_module")))]
+ LoadContextModule,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$prolog_lc_stream")))]
+ LoadContextStream,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$pop_load_context")))]
+ PopLoadContext,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$pop_load_state_payload")))]
+ PopLoadStatePayload,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$push_load_state_payload")))]
+ PushLoadStatePayload,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$push_load_context")))]
+ PushLoadContext,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$use_module")))]
+ UseModule,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$built_in_property")))]
+ BuiltInProperty,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$meta_predicate_property")))]
+ MetaPredicateProperty,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$multifile_property")))]
+ MultifileProperty,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$discontiguous_property")))]
+ DiscontiguousProperty,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$dynamic_property")))]
+ DynamicProperty,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$abolish_clause")))]
+ AbolishClause,
+ #[strum_discriminants(strum(props(Arity = "5", Name = "$asserta")))]
+ Asserta,
+ #[strum_discriminants(strum(props(Arity = "5", Name = "$assertz")))]
+ Assertz,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$retract_clause")))]
+ Retract,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$is_consistent_with_term_queue")))]
+ IsConsistentWithTermQueue,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$flush_term_queue")))]
+ FlushTermQueue,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$remove_module_exports")))]
+ RemoveModuleExports,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$add_non_counted_backtracking")))]
+ AddNonCountedBacktracking,
+}
+
+#[allow(dead_code)]
+#[derive(ToDeriveInput, EnumDiscriminants)]
+#[strum_discriminants(derive(EnumProperty, EnumString))]
+enum SystemClauseType {
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$atom_chars")))]
+ AtomChars,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$atom_codes")))]
+ AtomCodes,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$atom_length")))]
+ AtomLength,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$bind_from_register")))]
+ BindFromRegister,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$call_continuation")))]
+ CallContinuation,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$char_code")))]
+ CharCode,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$char_type")))]
+ CharType,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$chars_to_number")))]
+ CharsToNumber,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$codes_to_number")))]
+ CodesToNumber,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$copy_term_without_attr_vars")))]
+ CopyTermWithoutAttrVars,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$check_cp")))]
+ CheckCutPoint,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$close")))]
+ Close,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$copy_to_lh")))]
+ CopyToLiftedHeap,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$create_partial_string")))]
+ CreatePartialString,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$current_hostname")))]
+ CurrentHostname,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$current_input")))]
+ CurrentInput,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$current_output")))]
+ CurrentOutput,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$directory_files")))]
+ DirectoryFiles,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$file_size")))]
+ FileSize,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$file_exists")))]
+ FileExists,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$directory_exists")))]
+ DirectoryExists,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$directory_separator")))]
+ DirectorySeparator,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$make_directory")))]
+ MakeDirectory,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$make_directory_path")))]
+ MakeDirectoryPath,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$delete_file")))]
+ DeleteFile,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$rename_file")))]
+ RenameFile,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "working_directory")))]
+ WorkingDirectory,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$delete_directory")))]
+ DeleteDirectory,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$path_canonical")))]
+ PathCanonical,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$file_time")))]
+ FileTime,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$del_attr_non_head")))]
+ DeleteAttribute,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$del_attr_head")))]
+ DeleteHeadAttribute,
+ #[strum_discriminants(strum(props(Arity = "arity", Name = "$module_call")))]
+ DynamicModuleResolution(usize),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$enqueue_attr_var")))]
+ EnqueueAttributedVar,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$fetch_global_var")))]
+ FetchGlobalVar,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$first_stream")))]
+ FirstStream,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$flush_output")))]
+ FlushOutput,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$get_byte")))]
+ GetByte,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$get_char")))]
+ GetChar,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$get_n_chars")))]
+ GetNChars,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$get_code")))]
+ GetCode,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$get_single_char")))]
+ GetSingleChar,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$reset_attr_var_state")))]
+ ResetAttrVarState,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$truncate_if_no_lh_growth_diff")))]
+ TruncateIfNoLiftedHeapGrowthDiff,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$truncate_if_no_lh_growth")))]
+ TruncateIfNoLiftedHeapGrowth,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$get_attr_list")))]
+ GetAttributedVariableList,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$get_attr_var_queue_delim")))]
+ GetAttrVarQueueDelimiter,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$get_attr_var_queue_beyond")))]
+ GetAttrVarQueueBeyond,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$get_b_value")))]
+ GetBValue,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$get_cont_chunk")))]
+ GetContinuationChunk,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$get_next_db_ref")))]
+ GetNextDBRef,
+ #[strum_discriminants(strum(props(Arity = "7", Name = "$get_next_op_db_ref")))]
+ GetNextOpDBRef,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$is_partial_string")))]
+ IsPartialString,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$halt")))]
+ Halt,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$get_lh_from_offset")))]
+ GetLiftedHeapFromOffset,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$get_lh_from_offset_diff")))]
+ GetLiftedHeapFromOffsetDiff,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$get_scc_cleaner")))]
+ GetSCCCleaner,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$head_is_dynamic")))]
+ HeadIsDynamic,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$install_scc_cleaner")))]
+ InstallSCCCleaner,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$install_inference_counter")))]
+ InstallInferenceCounter,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$lh_length")))]
+ LiftedHeapLength,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$load_library_as_stream")))]
+ LoadLibraryAsStream,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$module_exists")))]
+ ModuleExists,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$nextEP")))]
+ NextEP,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$no_such_predicate")))]
+ NoSuchPredicate,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$number_to_chars")))]
+ NumberToChars,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$number_to_codes")))]
+ NumberToCodes,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$op")))]
+ OpDeclaration,
+ #[strum_discriminants(strum(props(Arity = "7", Name = "$open")))]
+ Open,
+ #[strum_discriminants(strum(props(Arity = "5", Name = "$set_stream_options")))]
+ SetStreamOptions,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$next_stream")))]
+ NextStream,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$partial_string_tail")))]
+ PartialStringTail,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$peek_byte")))]
+ PeekByte,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$peek_char")))]
+ PeekChar,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$peek_code")))]
+ PeekCode,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$points_to_cont_reset_marker")))]
+ PointsToContinuationResetMarker,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$put_byte")))]
+ PutByte,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$put_char")))]
+ PutChar,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$put_chars")))]
+ PutChars,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$put_code")))]
+ PutCode,
+ #[strum_discriminants(strum(props(Arity = "5", Name = "$read_query_term")))]
+ ReadQueryTerm,
+ #[strum_discriminants(strum(props(Arity = "5", Name = "$read_term")))]
+ ReadTerm,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$redo_attr_var_binding")))]
+ RedoAttrVarBinding,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$remove_call_policy_check")))]
+ RemoveCallPolicyCheck,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$remove_inference_counter")))]
+ RemoveInferenceCounter,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$reset_cont_marker")))]
+ ResetContinuationMarker,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$restore_cut_policy")))]
+ RestoreCutPolicy,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$set_cp")))]
+ SetCutPoint(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$set_input")))]
+ SetInput,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$set_output")))]
+ SetOutput,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$store_backtrackable_global_var")))]
+ StoreBacktrackableGlobalVar,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$store_global_var")))]
+ StoreGlobalVar,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$stream_property")))]
+ StreamProperty,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$set_stream_position")))]
+ SetStreamPosition,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$inference_level")))]
+ InferenceLevel,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$clean_up_block")))]
+ CleanUpBlock,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$erase_ball")))]
+ EraseBall,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$fail")))]
+ Fail,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$get_ball")))]
+ GetBall,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$get_current_block")))]
+ GetCurrentBlock,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$get_cp")))]
+ GetCutPoint,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$get_staggered_cp")))]
+ GetStaggeredCutPoint,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$get_double_quotes")))]
+ GetDoubleQuotes,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$install_new_block")))]
+ InstallNewBlock,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$maybe")))]
+ Maybe,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$current_time")))]
+ CurrentTime,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$quoted_token")))]
+ QuotedToken,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$read_term_from_chars")))]
+ ReadTermFromChars,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$reset_block")))]
+ ResetBlock,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$return_from_verify_attr")))]
+ ReturnFromVerifyAttr,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$set_ball")))]
+ SetBall,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$set_cp_by_default")))]
+ SetCutPointByDefault(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$set_double_quotes")))]
+ SetDoubleQuotes,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$set_seed")))]
+ SetSeed,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$skip_max_list")))]
+ SkipMaxList,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$sleep")))]
+ Sleep,
+ #[strum_discriminants(strum(props(Arity = "8", Name = "$socket_client_open")))]
+ SocketClientOpen,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$socket_server_open")))]
+ SocketServerOpen,
+ #[strum_discriminants(strum(props(Arity = "7", Name = "$socket_server_accept")))]
+ SocketServerAccept,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$socket_server_close")))]
+ SocketServerClose,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$tls_accept_client")))]
+ TLSAcceptClient,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$tls_client_connect")))]
+ TLSClientConnect,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$succeed")))]
+ Succeed,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$term_attributed_variables")))]
+ TermAttributedVariables,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$term_variables")))]
+ TermVariables,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$term_variables_under_max_depth")))]
+ TermVariablesUnderMaxDepth,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$truncate_lh_to")))]
+ TruncateLiftedHeapTo,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$unify_with_occurs_check")))]
+ UnifyWithOccursCheck,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$unwind_environments")))]
+ UnwindEnvironments,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$unwind_stack")))]
+ UnwindStack,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$wam_instructions")))]
+ WAMInstructions,
+ #[strum_discriminants(strum(props(Arity = "7", Name = "$write_term")))]
+ WriteTerm,
+ #[strum_discriminants(strum(props(Arity = "7", Name = "$write_term_to_chars")))]
+ WriteTermToChars,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$scryer_prolog_version")))]
+ ScryerPrologVersion,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$crypto_random_byte")))]
+ CryptoRandomByte,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$crypto_data_hash")))]
+ CryptoDataHash,
+ #[strum_discriminants(strum(props(Arity = "7", Name = "$crypto_data_hkdf")))]
+ CryptoDataHKDF,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$crypto_password_hash")))]
+ CryptoPasswordHash,
+ #[strum_discriminants(strum(props(Arity = "7", Name = "$crypto_data_encrypt")))]
+ CryptoDataEncrypt,
+ #[strum_discriminants(strum(props(Arity = "6", Name = "$crypto_data_decrypt")))]
+ CryptoDataDecrypt,
+ #[strum_discriminants(strum(props(Arity = "5", Name = "$crypto_curve_scalar_mult")))]
+ CryptoCurveScalarMult,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$ed25519_sign")))]
+ Ed25519Sign,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$ed25519_verify")))]
+ Ed25519Verify,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$ed25519_new_keypair")))]
+ Ed25519NewKeyPair,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$ed25519_keypair_public_key")))]
+ Ed25519KeyPairPublicKey,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$curve25519_scalar_mult")))]
+ Curve25519ScalarMult,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$first_non_octet")))]
+ FirstNonOctet,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$load_html")))]
+ LoadHTML,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "$load_xml")))]
+ LoadXML,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$getenv")))]
+ GetEnv,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$setenv")))]
+ SetEnv,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$unsetenv")))]
+ UnsetEnv,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$shell")))]
+ Shell,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$pid")))]
+ PID,
+ #[strum_discriminants(strum(props(Arity = "4", Name = "$chars_base64")))]
+ CharsBase64,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$devour_whitespace")))]
+ DevourWhitespace,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$is_sto_enabled")))]
+ IsSTOEnabled,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$set_sto_as_unify")))]
+ SetSTOAsUnify,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$set_nsto_as_unify")))]
+ SetNSTOAsUnify,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$set_sto_with_error_as_unify")))]
+ SetSTOWithErrorAsUnify,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$home_directory")))]
+ HomeDirectory,
+ #[strum_discriminants(strum(props(Arity = "0", Name = "$debug_hook")))]
+ DebugHook,
+ #[strum_discriminants(strum(props(Arity = "2", Name = "$popcount")))]
+ PopCount,
+ #[strum_discriminants(strum(props(Arity = "1", Name = "$cpu_now")))]
+ CpuNow,
+ REPL(REPLCodePtr),
+}
+
+#[allow(dead_code)]
+#[derive(ToDeriveInput, EnumDiscriminants)]
+#[strum_discriminants(derive(EnumProperty, EnumString))]
+enum InstructionTemplate {
+ #[strum_discriminants(strum(props(Arity = "3", Name = "get_constant")))]
+ GetConstant(Level, HeapCellValue, RegType),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "get_list")))]
+ GetList(Level, RegType),
+ #[strum_discriminants(strum(props(Arity = "4", Name = "get_partial_string")))]
+ GetPartialString(Level, Atom, RegType, bool),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "get_structure")))]
+ GetStructure(Atom, usize, RegType),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "get_variable")))]
+ GetVariable(RegType, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "get_value")))]
+ GetValue(RegType, usize),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "unify_constant")))]
+ UnifyConstant(HeapCellValue),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "unify_local_value")))]
+ UnifyLocalValue(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "unify_variable")))]
+ UnifyVariable(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "unify_value")))]
+ UnifyValue(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "unify_void")))]
+ UnifyVoid(usize),
+ // query instruction
+ #[strum_discriminants(strum(props(Arity = "3", Name = "put_constant")))]
+ PutConstant(Level, HeapCellValue, RegType),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "put_list")))]
+ PutList(Level, RegType),
+ #[strum_discriminants(strum(props(Arity = "4", Name = "put_partial_string")))]
+ PutPartialString(Level, Atom, RegType, bool),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "put_structure")))]
+ PutStructure(Atom, usize, RegType),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "put_unsafe_value")))]
+ PutUnsafeValue(usize, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "put_value")))]
+ PutValue(RegType, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "put_variable")))]
+ PutVariable(RegType, usize),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "set_constant")))]
+ SetConstant(HeapCellValue),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "set_local_value")))]
+ SetLocalValue(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "set_variable")))]
+ SetVariable(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "set_value")))]
+ SetValue(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "set_void")))]
+ SetVoid(usize),
+ // cut instruction
+ #[strum_discriminants(strum(props(Arity = "1", Name = "cut")))]
+ Cut(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "get_level")))]
+ GetLevel(RegType),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "get_level_and_unify")))]
+ GetLevelAndUnify(RegType),
+ #[strum_discriminants(strum(props(Arity = "0", Name = "neck_cut")))]
+ NeckCut,
+ // choice instruction
+ #[strum_discriminants(strum(props(Arity = "3", Name = "dynamic_else")))]
+ DynamicElse(usize, Death, NextOrFail),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "dynamic_internal_else")))]
+ DynamicInternalElse(usize, Death, NextOrFail),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "default_retry_me_else")))]
+ DefaultRetryMeElse(usize),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "default_trust_me")))]
+ DefaultTrustMe(usize),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "retry_me_else")))]
+ RetryMeElse(usize),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "trust_me")))]
+ TrustMe(usize),
+ #[strum_discriminants(strum(props(Arity = "1", Name = "default_trust_me")))]
+ TryMeElse(usize),
+ // arithmetic instruction
+ #[strum_discriminants(strum(props(Arity = "3", Name = "add")))]
+ Add(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "sub")))]
+ Sub(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "mul")))]
+ Mul(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "pow")))]
+ Pow(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "int_pow")))]
+ IntPow(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "i_div")))]
+ IDiv(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "max")))]
+ Max(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "min")))]
+ Min(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "int_floor_div")))]
+ IntFloorDiv(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "r_div")))]
+ RDiv(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "div")))]
+ Div(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "shl")))]
+ Shl(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "shr")))]
+ Shr(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "xor")))]
+ Xor(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "and")))]
+ And(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "or")))]
+ Or(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "mod")))]
+ Mod(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "rem")))]
+ Rem(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "gcd")))]
+ Gcd(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "sign")))]
+ Sign(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "cos")))]
+ Cos(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "sin")))]
+ Sin(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "tan")))]
+ Tan(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "log")))]
+ Log(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "exp")))]
+ Exp(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "acos")))]
+ ACos(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "asin")))]
+ ASin(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "atan")))]
+ ATan(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "3", Name = "atan2")))]
+ ATan2(ArithmeticTerm, ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "sqrt")))]
+ Sqrt(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "abs")))]
+ Abs(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "float")))]
+ Float(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "truncate")))]
+ Truncate(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "round")))]
+ Round(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "ceiling")))]
+ Ceiling(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "floor")))]
+ Floor(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "neg")))]
+ Neg(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "plus")))]
+ Plus(ArithmeticTerm, usize),
+ #[strum_discriminants(strum(props(Arity = "2", Name = "bitwise_complement")))]
+ BitwiseComplement(ArithmeticTerm, usize),
+ // control instructions
+ #[strum_discriminants(strum(props(Arity = "1", Name = "allocate")))]
+ Allocate(usize), // num_frames.
+ #[strum_discriminants(strum(props(Arity = "0", Name = "deallocate")))]
+ Deallocate,
+ #[strum_discriminants(strum(props(Arity = "3", Name = "jmp_by_call")))]
+ JmpByCall(usize, usize), // arity, relative offset.
+ #[strum_discriminants(strum(props(Arity = "3", Name = "jmp_by_execute")))]
+ JmpByExecute(usize, usize), // arity, relative offset.
+ #[strum_discriminants(strum(props(Arity = "1", Name = "rev_jmp_by")))]
+ RevJmpBy(usize),
+ #[strum_discriminants(strum(props(Arity = "0", Name = "proceed")))]
+ Proceed,
+ // indexing.
+ #[strum_discriminants(strum(props(Arity = "1", Name = "indexing_code")))]
+ IndexingCode(Vec<IndexingLine>),
+ // break from loop instruction.
+ #[strum_discriminants(strum(props(Arity = "0", Name = "break_from_dispatch")))]
+ BreakFromDispatchLoop,
+ // swap the verify attr interrupt instruction with the next control instruction.
+ #[strum_discriminants(strum(props(Arity = "0", Name = "install_verify_attr")))]
+ InstallVerifyAttr,
+ // call verify_attrs.
+ #[strum_discriminants(strum(props(Arity = "0", Name = "verify_attr_interrupt")))]
+ VerifyAttrInterrupt,
+ // procedures
+ CallClause(ClauseType, usize, usize, bool, bool), // ClauseType,
+ // arity,
+ // perm_vars,
+ // last_call,
+ // use_default_call_policy.
+}
+
+fn derive_input(ty: &Type) -> Option<DeriveInput> {
+ let clause_type: Type = parse_quote!{ ClauseType };
+ let built_in_clause_type: Type = parse_quote! { BuiltInClauseType };
+ let inlined_clause_type: Type = parse_quote! { InlinedClauseType };
+ let system_clause_type: Type = parse_quote! { SystemClauseType };
+ let compare_term_type: Type = parse_quote! { CompareTerm };
+ let compare_number_type: Type = parse_quote! { CompareNumber };
+ let repl_code_ptr_type: Type = parse_quote! { REPLCodePtr };
+
+ if ty == &clause_type {
+ Some(ClauseType::to_derive_input())
+ } else if ty == &built_in_clause_type {
+ Some(BuiltInClauseType::to_derive_input())
+ } else if ty == &inlined_clause_type {
+ Some(InlinedClauseType::to_derive_input())
+ } else if ty == &system_clause_type {
+ Some(SystemClauseType::to_derive_input())
+ } else if ty == &compare_number_type {
+ Some(CompareNumber::to_derive_input())
+ } else if ty == &compare_term_type {
+ Some(CompareTerm::to_derive_input())
+ } else if ty == &repl_code_ptr_type {
+ Some(REPLCodePtr::to_derive_input())
+ } else {
+ None
+ }
+}
+
+impl ToTokens for Arity {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ match self {
+ Arity::Static(arity) => {
+ arity.to_tokens(tokens);
+ }
+ Arity::Ident(arity) => {
+ let ident = format_ident!("{}", arity);
+ tokens.append(ident);
+ }
+ }
+ }
+}
+
+fn add_discriminant_data<DiscriminantT>(
+ variant: &Variant,
+ prefix: &'static str,
+ variant_data: &mut Vec<(&'static str, Arity, Variant)>,
+) -> (&'static str, Arity)
+ where DiscriminantT: FromStr + strum::EnumProperty + std::fmt::Debug
+{
+ let name = prop_from_ident::<DiscriminantT>(&variant.ident, "Name");
+ let arity = Arity::from(prop_from_ident::<DiscriminantT>(&variant.ident, "Arity"));
+
+ if prefix == "Call" {
+ let mut variant = variant.clone();
+ variant.attrs.clear();
+
+ variant_data.push((name, arity, variant));
+ }
+
+ (name, arity)
+}
+
+fn generate_instruction_preface() -> TokenStream {
+ quote! {
+ use crate::arena::*;
+ use crate::arithmetic::*;
+ use crate::atom_table::*;
+ use crate::forms::*;
+ use crate::machine::heap::*;
+ use crate::machine::machine_errors::MachineStub;
+ use crate::machine::machine_indices::CodeIndex;
+ use crate::parser::ast::*;
+ use crate::types::*;
+
+ use indexmap::IndexMap;
+ use slice_deque::SliceDeque;
+
+ fn reg_type_into_functor(r: RegType) -> MachineStub {
+ match r {
+ RegType::Temp(r) => functor!(atom!("x"), [fixnum(r)]),
+ RegType::Perm(r) => functor!(atom!("y"), [fixnum(r)]),
+ }
+ }
+
+ impl Level {
+ fn into_functor(self) -> MachineStub {
+ match self {
+ Level::Root => functor!(atom!("level"), [atom(atom!("root"))]),
+ Level::Shallow => functor!(atom!("level"), [atom(atom!("shallow"))]),
+ Level::Deep => functor!(atom!("level"), [atom(atom!("deep"))]),
+ }
+ }
+ }
+
+ impl ArithmeticTerm {
+ fn into_functor(&self, arena: &mut Arena) -> MachineStub {
+ match self {
+ &ArithmeticTerm::Reg(r) => reg_type_into_functor(r),
+ &ArithmeticTerm::Interm(i) => {
+ functor!(atom!("intermediate"), [fixnum(i)])
+ }
+ &ArithmeticTerm::Number(n) => {
+ vec![HeapCellValue::from((n, arena))]
+ }
+ }
+ }
+ }
+
+ #[derive(Debug, Clone, Copy)]
+ pub enum NextOrFail {
+ Next(usize),
+ Fail(usize),
+ }
+
+ impl Default for NextOrFail {
+ fn default() -> Self {
+ NextOrFail::Fail(0)
+ }
+ }
+
+ impl NextOrFail {
+ #[inline]
+ pub fn is_next(&self) -> bool {
+ if let NextOrFail::Next(_) = self {
+ true
+ } else {
+ false
+ }
+ }
+ }
+
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+ pub enum Death {
+ Finite(usize),
+ Infinity,
+ }
+
+ impl Default for Death {
+ fn default() -> Self {
+ Death::Infinity
+ }
+ }
+
+ #[derive(Clone, Copy, Debug)]
+ pub enum IndexedChoiceInstruction {
+ Retry(usize),
+ Trust(usize),
+ Try(usize),
+ }
+
+ impl IndexedChoiceInstruction {
+ pub(crate) fn offset(&self) -> usize {
+ match self {
+ &IndexedChoiceInstruction::Retry(offset) => offset,
+ &IndexedChoiceInstruction::Trust(offset) => offset,
+ &IndexedChoiceInstruction::Try(offset) => offset,
+ }
+ }
+
+ pub(crate) fn to_functor(&self) -> MachineStub {
+ match self {
+ &IndexedChoiceInstruction::Try(offset) => {
+ functor!(atom!("try"), [fixnum(offset)])
+ }
+ &IndexedChoiceInstruction::Trust(offset) => {
+ functor!(atom!("trust"), [fixnum(offset)])
+ }
+ &IndexedChoiceInstruction::Retry(offset) => {
+ functor!(atom!("retry"), [fixnum(offset)])
+ }
+ }
+ }
+ }
+
+ /// `IndexingInstruction` cf. page 110 of wambook.
+ #[derive(Clone, Debug)]
+ pub enum IndexingInstruction {
+ // The first index is the optimal argument being indexed.
+ SwitchOnTerm(
+ usize,
+ IndexingCodePtr,
+ IndexingCodePtr,
+ IndexingCodePtr,
+ IndexingCodePtr,
+ ),
+ SwitchOnConstant(IndexMap<Literal, IndexingCodePtr>),
+ SwitchOnStructure(IndexMap<(Atom, usize), IndexingCodePtr>),
+ }
+
+ #[derive(Debug, Clone, Copy)]
+ pub enum IndexingCodePtr {
+ External(usize), // the index points past the indexing instruction prelude.
+ DynamicExternal(usize), // an External index of a dynamic predicate, potentially invalidated by retraction.
+ Fail,
+ Internal(usize), // the index points into the indexing instruction prelude.
+ }
+
+ impl IndexingCodePtr {
+ #[allow(dead_code)]
+ pub fn to_functor(self) -> MachineStub {
+ match self {
+ IndexingCodePtr::DynamicExternal(o) => functor!(atom!("dynamic_external"), [fixnum(o)]),
+ IndexingCodePtr::External(o) => functor!(atom!("external"), [fixnum(o)]),
+ IndexingCodePtr::Internal(o) => functor!(atom!("internal"), [fixnum(o)]),
+ IndexingCodePtr::Fail => {
+ vec![atom_as_cell!(atom!("fail"))]
+ },
+ }
+ }
+ }
+
+ impl IndexingInstruction {
+ pub fn to_functor(&self, mut h: usize) -> MachineStub {
+ match self {
+ &IndexingInstruction::SwitchOnTerm(arg, vars, constants, lists, structures) => {
+ functor!(
+ atom!("switch_on_term"),
+ [
+ fixnum(arg),
+ indexing_code_ptr(h, vars),
+ indexing_code_ptr(h, constants),
+ indexing_code_ptr(h, lists),
+ indexing_code_ptr(h, structures)
+ ]
+ )
+ }
+ &IndexingInstruction::SwitchOnConstant(ref constants) => {
+ let mut key_value_list_stub = vec![];
+ let orig_h = h;
+
+ h += 2; // skip the 2-cell "switch_on_constant" functor.
+
+ for (c, ptr) in constants.iter() {
+ let key_value_pair = functor!(
+ atom!(":"),
+ [literal(*c), indexing_code_ptr(h + 3, *ptr)]
+ );
+
+ key_value_list_stub.push(list_loc_as_cell!(h + 1));
+ key_value_list_stub.push(str_loc_as_cell!(h + 3));
+ key_value_list_stub.push(heap_loc_as_cell!(h + 3 + key_value_pair.len()));
+
+ h += key_value_pair.len() + 3;
+ key_value_list_stub.extend(key_value_pair.into_iter());
+ }
+
+ key_value_list_stub.push(empty_list_as_cell!());
+
+ functor!(
+ atom!("switch_on_constant"),
+ [str(orig_h, 0)],
+ [key_value_list_stub]
+ )
+ }
+ &IndexingInstruction::SwitchOnStructure(ref structures) => {
+ let mut key_value_list_stub = vec![];
+ let orig_h = h;
+
+ h += 2; // skip the 2-cell "switch_on_constant" functor.
+
+ for ((name, arity), ptr) in structures.iter() {
+ let predicate_indicator_stub = functor!(
+ atom!("/"),
+ [atom(name), fixnum(*arity)]
+ );
+
+ let key_value_pair = functor!(
+ atom!(":"),
+ [str(h + 3, 0), indexing_code_ptr(h + 3, *ptr)],
+ [predicate_indicator_stub]
+ );
+
+ key_value_list_stub.push(list_loc_as_cell!(h + 1));
+ key_value_list_stub.push(str_loc_as_cell!(h + 3));
+ key_value_list_stub.push(heap_loc_as_cell!(h + 3 + key_value_pair.len()));
+
+ h += key_value_pair.len() + 3;
+ key_value_list_stub.extend(key_value_pair.into_iter());
+ }
+
+ key_value_list_stub.push(empty_list_as_cell!());
+
+ functor!(
+ atom!("switch_on_structure"),
+ [str(orig_h, 0)],
+ [key_value_list_stub]
+ )
+ }
+ }
+ }
+ }
+
+ /// A `Line` is an instruction (cf. page 98 of wambook).
+ #[derive(Clone, Debug)]
+ pub enum IndexingLine {
+ Indexing(IndexingInstruction),
+ IndexedChoice(SliceDeque<IndexedChoiceInstruction>),
+ DynamicIndexedChoice(SliceDeque<usize>),
+ }
+
+ impl From<IndexingInstruction> for IndexingLine {
+ #[inline]
+ fn from(instr: IndexingInstruction) -> Self {
+ IndexingLine::Indexing(instr)
+ }
+ }
+
+ impl From<SliceDeque<IndexedChoiceInstruction>> for IndexingLine {
+ #[inline]
+ fn from(instrs: SliceDeque<IndexedChoiceInstruction>) -> Self {
+ IndexingLine::IndexedChoice(instrs)
+ }
+ }
+
+ fn arith_instr_unary_functor(
+ h: usize,
+ name: Atom,
+ arena: &mut Arena,
+ at: &ArithmeticTerm,
+ t: usize,
+ ) -> MachineStub {
+ let at_stub = at.into_functor(arena);
+ functor!(name, [str(h, 0), fixnum(t)], [at_stub])
+ }
+
+ fn arith_instr_bin_functor(
+ h: usize,
+ name: Atom,
+ arena: &mut Arena,
+ at_1: &ArithmeticTerm,
+ at_2: &ArithmeticTerm,
+ t: usize,
+ ) -> MachineStub {
+ let at_1_stub = at_1.into_functor(arena);
+ let at_2_stub = at_2.into_functor(arena);
+
+ functor!(
+ name,
+ [str(h, 0), str(h, 1), fixnum(t)],
+ [at_1_stub, at_2_stub]
+ )
+ }
+
+ pub type Code = Vec<Instruction>;
+
+ impl Instruction {
+ #[inline]
+ pub fn to_indexing_line_mut(&mut self) -> Option<&mut Vec<IndexingLine>> {
+ match self {
+ Instruction::IndexingCode(ref mut indexing_code) => Some(indexing_code),
+ _ => None,
+ }
+ }
+
+ #[inline]
+ pub fn to_indexing_line(&self) -> Option<&Vec<IndexingLine>> {
+ match self {
+ Instruction::IndexingCode(ref indexing_code) => Some(indexing_code),
+ _ => None,
+ }
+ }
+
+ #[inline]
+ pub fn is_head_instr(&self) -> bool {
+ match self {
+ Instruction::GetConstant(..) |
+ Instruction::GetList(..) |
+ Instruction::GetPartialString(..) |
+ Instruction::GetStructure(..) |
+ Instruction::GetValue(..) |
+ Instruction::UnifyConstant(..) |
+ Instruction::UnifyLocalValue(..) |
+ Instruction::UnifyVariable(..) |
+ Instruction::UnifyValue(..) |
+ Instruction::UnifyVoid(..) |
+ Instruction::GetVariable(..) |
+ Instruction::PutConstant(..) |
+ Instruction::PutList(..) |
+ Instruction::PutPartialString(..) |
+ Instruction::PutStructure(..) |
+ Instruction::PutUnsafeValue(..) |
+ Instruction::PutValue(..) |
+ Instruction::PutVariable(..) |
+ Instruction::SetConstant(..) |
+ Instruction::SetLocalValue(..) |
+ Instruction::SetVariable(..) |
+ Instruction::SetValue(..) |
+ Instruction::SetVoid(..) => true,
+ _ => false,
+ }
+ }
+
+ pub fn enqueue_functors(
+ &self,
+ mut h: usize,
+ arena: &mut Arena,
+ functors: &mut Vec<MachineStub>,
+ ) {
+ match self {
+ &Instruction::IndexingCode(ref indexing_instrs) => {
+ for indexing_instr in indexing_instrs {
+ match indexing_instr {
+ IndexingLine::Indexing(indexing_instr) => {
+ let section = indexing_instr.to_functor(h);
+ h += section.len();
+ functors.push(section);
+ }
+ IndexingLine::IndexedChoice(indexed_choice_instrs) => {
+ for indexed_choice_instr in indexed_choice_instrs {
+ let section = indexed_choice_instr.to_functor();
+ h += section.len();
+ functors.push(section);
+ }
+ }
+ IndexingLine::DynamicIndexedChoice(indexed_choice_instrs) => {
+ for indexed_choice_instr in indexed_choice_instrs {
+ let section = functor!(atom!("dynamic"), [fixnum(*indexed_choice_instr)]);
+
+ h += section.len();
+ functors.push(section);
+ }
+ }
+ }
+ }
+ }
+ instr => functors.push(instr.to_functor(h, arena)),
+ }
+ }
+
+ fn to_functor(&self, h: usize, arena: &mut Arena) -> MachineStub {
+ match self {
+ &Instruction::InstallVerifyAttr => {
+ functor!(atom!("install_verify_attr"))
+ }
+ &Instruction::VerifyAttrInterrupt => {
+ functor!(atom!("verify_attr_interrupt"))
+ }
+ &Instruction::DynamicElse(birth, death, next_or_fail) => {
+ match (death, next_or_fail) {
+ (Death::Infinity, NextOrFail::Next(i)) => {
+ functor!(
+ atom!("dynamic_else"),
+ [fixnum(birth), atom(atom!("inf")), fixnum(i)]
+ )
+ }
+ (Death::Infinity, NextOrFail::Fail(i)) => {
+ let next_functor = functor!(atom!("fail"), [fixnum(i)]);
+
+ functor!(
+ atom!("dynamic_else"),
+ [fixnum(birth), atom(atom!("inf")), str(h, 0)],
+ [next_functor]
+ )
+ }
+ (Death::Finite(d), NextOrFail::Fail(i)) => {
+ let next_functor = functor!(atom!("fail"), [fixnum(i)]);
+
+ functor!(
+ atom!("dynamic_else"),
+ [fixnum(birth), fixnum(d), str(h, 0)],
+ [next_functor]
+ )
+ }
+ (Death::Finite(d), NextOrFail::Next(i)) => {
+ functor!(atom!("dynamic_else"), [fixnum(birth), fixnum(d), fixnum(i)])
+ }
+ }
+ }
+ &Instruction::DynamicInternalElse(birth, death, next_or_fail) => {
+ match (death, next_or_fail) {
+ (Death::Infinity, NextOrFail::Next(i)) => {
+ functor!(
+ atom!("dynamic_internal_else"),
+ [fixnum(birth), atom(atom!("inf")), fixnum(i)]
+ )
+ }
+ (Death::Infinity, NextOrFail::Fail(i)) => {
+ let next_functor = functor!(atom!("fail"), [fixnum(i)]);
+
+ functor!(
+ atom!("dynamic_internal_else"),
+ [fixnum(birth), atom(atom!("inf")), str(h, 0)],
+ [next_functor]
+ )
+ }
+ (Death::Finite(d), NextOrFail::Fail(i)) => {
+ let next_functor = functor!(atom!("fail"), [fixnum(i)]);
+
+ functor!(
+ atom!("dynamic_internal_else"),
+ [fixnum(birth), fixnum(d), str(h, 0)],
+ [next_functor]
+ )
+ }
+ (Death::Finite(d), NextOrFail::Next(i)) => {
+ functor!(
+ atom!("dynamic_internal_else"),
+ [fixnum(birth), fixnum(d), fixnum(i)]
+ )
+ }
+ }
+ }
+ &Instruction::TryMeElse(offset) => {
+ functor!(atom!("try_me_else"), [fixnum(offset)])
+ }
+ &Instruction::RetryMeElse(offset) => {
+ functor!(atom!("retry_me_else"), [fixnum(offset)])
+ }
+ &Instruction::TrustMe(offset) => {
+ functor!(atom!("trust_me"), [fixnum(offset)])
+ }
+ &Instruction::DefaultRetryMeElse(offset) => {
+ functor!(atom!("default_retry_me_else"), [fixnum(offset)])
+ }
+ &Instruction::DefaultTrustMe(offset) => {
+ functor!(atom!("default_trust_me"), [fixnum(offset)])
+ }
+ &Instruction::Cut(r) => {
+ let rt_stub = reg_type_into_functor(r);
+ functor!(atom!("cut"), [str(h, 0)], [rt_stub])
+ }
+ &Instruction::GetLevel(r) => {
+ let rt_stub = reg_type_into_functor(r);
+ functor!(atom!("get_level"), [str(h, 0)], [rt_stub])
+ }
+ &Instruction::GetLevelAndUnify(r) => {
+ let rt_stub = reg_type_into_functor(r);
+ functor!(atom!("get_level_and_unify"), [str(h, 0)], [rt_stub])
+ }
+ &Instruction::NeckCut => {
+ functor!(atom!("neck_cut"))
+ }
+ &Instruction::Add(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("add"), arena, at_1, at_2, t)
+ }
+ &Instruction::Sub(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("sub"), arena, at_1, at_2, t)
+ }
+ &Instruction::Mul(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("mul"), arena, at_1, at_2, t)
+ }
+ &Instruction::IntPow(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("int_pow"), arena, at_1, at_2, t)
+ }
+ &Instruction::Pow(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("pow"), arena, at_1, at_2, t)
+ }
+ &Instruction::IDiv(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("idiv"), arena, at_1, at_2, t)
+ }
+ &Instruction::Max(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("max"), arena, at_1, at_2, t)
+ }
+ &Instruction::Min(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("min"), arena, at_1, at_2, t)
+ }
+ &Instruction::IntFloorDiv(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("int_floor_div"), arena, at_1, at_2, t)
+ }
+ &Instruction::RDiv(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("rdiv"), arena, at_1, at_2, t)
+ }
+ &Instruction::Div(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("div"), arena, at_1, at_2, t)
+ }
+ &Instruction::Shl(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("shl"), arena, at_1, at_2, t)
+ }
+ &Instruction::Shr(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("shr"), arena, at_1, at_2, t)
+ }
+ &Instruction::Xor(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("xor"), arena, at_1, at_2, t)
+ }
+ &Instruction::And(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("and"), arena, at_1, at_2, t)
+ }
+ &Instruction::Or(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("or"), arena, at_1, at_2, t)
+ }
+ &Instruction::Mod(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("mod"), arena, at_1, at_2, t)
+ }
+ &Instruction::Rem(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("rem"), arena, at_1, at_2, t)
+ }
+ &Instruction::ATan2(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("rem"), arena, at_1, at_2, t)
+ }
+ &Instruction::Gcd(ref at_1, ref at_2, t) => {
+ arith_instr_bin_functor(h, atom!("gcd"), arena, at_1, at_2, t)
+ }
+ &Instruction::Sign(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("sign"), arena, at, t)
+ }
+ &Instruction::Cos(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("cos"), arena, at, t)
+ }
+ &Instruction::Sin(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("sin"), arena, at, t)
+ }
+ &Instruction::Tan(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("tan"), arena, at, t)
+ }
+ &Instruction::Log(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("log"), arena, at, t)
+ }
+ &Instruction::Exp(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("exp"), arena, at, t)
+ }
+ &Instruction::ACos(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("acos"), arena, at, t)
+ }
+ &Instruction::ASin(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("asin"), arena, at, t)
+ }
+ &Instruction::ATan(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("atan"), arena, at, t)
+ }
+ &Instruction::Sqrt(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("sqrt"), arena, at, t)
+ }
+ &Instruction::Abs(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("abs"), arena, at, t)
+ }
+ &Instruction::Float(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("float"), arena, at, t)
+ }
+ &Instruction::Truncate(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("truncate"), arena, at, t)
+ }
+ &Instruction::Round(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("round"), arena, at, t)
+ }
+ &Instruction::Ceiling(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("ceiling"), arena, at, t)
+ }
+ &Instruction::Floor(ref at, t) => {
+ arith_instr_unary_functor(h, atom!("floor"), arena, at, t)
+ }
+ &Instruction::Neg(ref at, t) => arith_instr_unary_functor(
+ h,
+ atom!("-"),
+ arena,
+ at,
+ t,
+ ),
+ &Instruction::Plus(ref at, t) => arith_instr_unary_functor(
+ h,
+ atom!("+"),
+ arena,
+ at,
+ t,
+ ),
+ &Instruction::BitwiseComplement(ref at, t) => arith_instr_unary_functor(
+ h,
+ atom!("\\"),
+ arena,
+ at,
+ t,
+ ),
+ &Instruction::IndexingCode(_) => {
+ // this case is covered in enqueue_functors, which
+ // should be called instead (to_functor is a private
+ // function for this reason).
+ vec![]
+ }
+ &Instruction::Allocate(num_frames) => {
+ functor!(atom!("allocate"), [fixnum(num_frames)])
+ }
+ &Instruction::CallNamed(arity, name, ..) => {
+ functor!(atom!("call"), [atom(name), fixnum(arity)])
+ }
+ &Instruction::ExecuteNamed(arity, name, ..) => {
+ functor!(atom!("execute"), [atom(name), fixnum(arity)])
+ }
+ &Instruction::DefaultCallNamed(arity, name, ..) => {
+ functor!(atom!("call_default"), [atom(name), fixnum(arity)])
+ }
+ &Instruction::DefaultExecuteNamed(arity, name, ..) => {
+ functor!(atom!("execute_default"), [atom(name), fixnum(arity)])
+ }
+ &Instruction::CallN(arity, _) => {
+ functor!(atom!("call_n"), [fixnum(arity)])
+ }
+ &Instruction::ExecuteN(arity, _) => {
+ functor!(atom!("execute_n"), [fixnum(arity)])
+ }
+ &Instruction::DefaultCallN(arity, _) => {
+ functor!(atom!("call_default_n"), [fixnum(arity)])
+ }
+ &Instruction::DefaultExecuteN(arity, _) => {
+ functor!(atom!("execute_default_n"), [fixnum(arity)])
+ }
+ &Instruction::CallTermGreaterThan(_) |
+ &Instruction::CallTermLessThan(_) |
+ &Instruction::CallTermGreaterThanOrEqual(_) |
+ &Instruction::CallTermLessThanOrEqual(_) |
+ &Instruction::CallTermEqual(_) |
+ &Instruction::CallTermNotEqual(_) |
+ &Instruction::CallNumberGreaterThan(..) |
+ &Instruction::CallNumberLessThan(..) |
+ &Instruction::CallNumberGreaterThanOrEqual(..) |
+ &Instruction::CallNumberLessThanOrEqual(..) |
+ &Instruction::CallNumberEqual(..) |
+ &Instruction::CallNumberNotEqual(..) |
+ &Instruction::CallIs(..) |
+ &Instruction::CallAcyclicTerm(_) |
+ &Instruction::CallArg(_) |
+ &Instruction::CallCompare(_) |
+ &Instruction::CallCopyTerm(_) |
+ &Instruction::CallFunctor(_) |
+ &Instruction::CallGround(_) |
+ &Instruction::CallKeySort(_) |
+ &Instruction::CallRead(_) |
+ &Instruction::CallSort(_) => {
+ let (name, arity) = self.to_name_and_arity();
+ functor!(atom!("call"), [atom(name), fixnum(arity)])
+ }
+ //
+ &Instruction::ExecuteTermGreaterThan(_) |
+ &Instruction::ExecuteTermLessThan(_) |
+ &Instruction::ExecuteTermGreaterThanOrEqual(_) |
+ &Instruction::ExecuteTermLessThanOrEqual(_) |
+ &Instruction::ExecuteTermEqual(_) |
+ &Instruction::ExecuteTermNotEqual(_) |
+ &Instruction::ExecuteNumberGreaterThan(..) |
+ &Instruction::ExecuteNumberLessThan(..) |
+ &Instruction::ExecuteNumberGreaterThanOrEqual(..) |
+ &Instruction::ExecuteNumberLessThanOrEqual(..) |
+ &Instruction::ExecuteNumberEqual(..) |
+ &Instruction::ExecuteNumberNotEqual(..) |
+ &Instruction::ExecuteAcyclicTerm(_) |
+ &Instruction::ExecuteArg(_) |
+ &Instruction::ExecuteCompare(_) |
+ &Instruction::ExecuteCopyTerm(_) |
+ &Instruction::ExecuteFunctor(_) |
+ &Instruction::ExecuteGround(_) |
+ &Instruction::ExecuteIs(..) |
+ &Instruction::ExecuteKeySort(_) |
+ &Instruction::ExecuteRead(_) |
+ &Instruction::ExecuteSort(_) => {
+ let (name, arity) = self.to_name_and_arity();
+ functor!(atom!("execute"), [atom(name), fixnum(arity)])
+ }
+ //
+ &Instruction::DefaultCallTermGreaterThan(_) |
+ &Instruction::DefaultCallTermLessThan(_) |
+ &Instruction::DefaultCallTermGreaterThanOrEqual(_) |
+ &Instruction::DefaultCallTermLessThanOrEqual(_) |
+ &Instruction::DefaultCallTermEqual(_) |
+ &Instruction::DefaultCallTermNotEqual(_) |
+ &Instruction::DefaultCallNumberGreaterThan(..) |
+ &Instruction::DefaultCallNumberLessThan(..) |
+ &Instruction::DefaultCallNumberGreaterThanOrEqual(..) |
+ &Instruction::DefaultCallNumberLessThanOrEqual(..) |
+ &Instruction::DefaultCallNumberEqual(..) |
+ &Instruction::DefaultCallNumberNotEqual(..) |
+ &Instruction::DefaultCallAcyclicTerm(_) |
+ &Instruction::DefaultCallArg(_) |
+ &Instruction::DefaultCallCompare(_) |
+ &Instruction::DefaultCallCopyTerm(_) |
+ &Instruction::DefaultCallFunctor(_) |
+ &Instruction::DefaultCallGround(_) |
+ &Instruction::DefaultCallIs(..) |
+ &Instruction::DefaultCallKeySort(_) |
+ &Instruction::DefaultCallRead(_) |
+ &Instruction::DefaultCallSort(_) => {
+ let (name, arity) = self.to_name_and_arity();
+ functor!(atom!("call_default"), [atom(name), fixnum(arity)])
+ }
+ //
+ &Instruction::DefaultExecuteTermGreaterThan(_) |
+ &Instruction::DefaultExecuteTermLessThan(_) |
+ &Instruction::DefaultExecuteTermGreaterThanOrEqual(_) |
+ &Instruction::DefaultExecuteTermLessThanOrEqual(_) |
+ &Instruction::DefaultExecuteTermEqual(_) |
+ &Instruction::DefaultExecuteTermNotEqual(_) |
+ &Instruction::DefaultExecuteNumberGreaterThan(..) |
+ &Instruction::DefaultExecuteNumberLessThan(..) |
+ &Instruction::DefaultExecuteNumberGreaterThanOrEqual(..) |
+ &Instruction::DefaultExecuteNumberLessThanOrEqual(..) |
+ &Instruction::DefaultExecuteNumberEqual(..) |
+ &Instruction::DefaultExecuteNumberNotEqual(..) |
+ &Instruction::DefaultExecuteAcyclicTerm(_) |
+ &Instruction::DefaultExecuteArg(_) |
+ &Instruction::DefaultExecuteCompare(_) |
+ &Instruction::DefaultExecuteCopyTerm(_) |
+ &Instruction::DefaultExecuteFunctor(_) |
+ &Instruction::DefaultExecuteGround(_) |
+ &Instruction::DefaultExecuteIs(..) |
+ &Instruction::DefaultExecuteKeySort(_) |
+ &Instruction::DefaultExecuteRead(_) |
+ &Instruction::DefaultExecuteSort(_) => {
+ let (name, arity) = self.to_name_and_arity();
+ functor!(atom!("execute_default"), [atom(name), fixnum(arity)])
+ }
+ &Instruction::CallIsAtom(_, _) |
+ &Instruction::CallIsAtomic(_, _) |
+ &Instruction::CallIsCompound(_, _) |
+ &Instruction::CallIsInteger(_, _) |
+ &Instruction::CallIsNumber(_, _) |
+ &Instruction::CallIsRational(_, _) |
+ &Instruction::CallIsFloat(_, _) |
+ &Instruction::CallIsNonVar(_, _) |
+ &Instruction::CallIsVar(_, _) => {
+ let (name, arity) = self.to_name_and_arity();
+ functor!(atom!("call"), [atom(name), fixnum(arity)])
+ }
+ &Instruction::ExecuteIsAtom(_, _) |
+ &Instruction::ExecuteIsAtomic(_, _) |
+ &Instruction::ExecuteIsCompound(_, _) |
+ &Instruction::ExecuteIsInteger(_, _) |
+ &Instruction::ExecuteIsNumber(_, _) |
+ &Instruction::ExecuteIsRational(_, _) |
+ &Instruction::ExecuteIsFloat(_, _) |
+ &Instruction::ExecuteIsNonVar(_, _) |
+ &Instruction::ExecuteIsVar(_, _) => {
+ let (name, arity) = self.to_name_and_arity();
+ functor!(atom!("execute"), [atom(name), fixnum(arity)])
+ }
+ //
+ &Instruction::CallAtomChars(_) |
+ &Instruction::CallAtomCodes(_) |
+ &Instruction::CallAtomLength(_) |
+ &Instruction::CallBindFromRegister(_) |
+ &Instruction::CallContinuation(_) |
+ &Instruction::CallCharCode(_) |
+ &Instruction::CallCharType(_) |
+ &Instruction::CallCharsToNumber(_) |
+ &Instruction::CallCodesToNumber(_) |
+ &Instruction::CallCopyTermWithoutAttrVars(_) |
+ &Instruction::CallCheckCutPoint(_) |
+ &Instruction::CallClose(_) |
+ &Instruction::CallCopyToLiftedHeap(_) |
+ &Instruction::CallCreatePartialString(_) |
+ &Instruction::CallCurrentHostname(_) |
+ &Instruction::CallCurrentInput(_) |
+ &Instruction::CallCurrentOutput(_) |
+ &Instruction::CallDirectoryFiles(_) |
+ &Instruction::CallFileSize(_) |
+ &Instruction::CallFileExists(_) |
+ &Instruction::CallDirectoryExists(_) |
+ &Instruction::CallDirectorySeparator(_) |
+ &Instruction::CallMakeDirectory(_) |
+ &Instruction::CallMakeDirectoryPath(_) |
+ &Instruction::CallDeleteFile(_) |
+ &Instruction::CallRenameFile(_) |
+ &Instruction::CallWorkingDirectory(_) |
+ &Instruction::CallDeleteDirectory(_) |
+ &Instruction::CallPathCanonical(_) |
+ &Instruction::CallFileTime(_) |
+ &Instruction::CallDeleteAttribute(_) |
+ &Instruction::CallDeleteHeadAttribute(_) |
+ &Instruction::CallDynamicModuleResolution(..) |
+ &Instruction::CallEnqueueAttributedVar(_) |
+ &Instruction::CallFetchGlobalVar(_) |
+ &Instruction::CallFirstStream(_) |
+ &Instruction::CallFlushOutput(_) |
+ &Instruction::CallGetByte(_) |
+ &Instruction::CallGetChar(_) |
+ &Instruction::CallGetNChars(_) |
+ &Instruction::CallGetCode(_) |
+ &Instruction::CallGetSingleChar(_) |
+ &Instruction::CallResetAttrVarState(_) |
+ &Instruction::CallTruncateIfNoLiftedHeapGrowthDiff(_) |
+ &Instruction::CallTruncateIfNoLiftedHeapGrowth(_) |
+ &Instruction::CallGetAttributedVariableList(_) |
+ &Instruction::CallGetAttrVarQueueDelimiter(_) |
+ &Instruction::CallGetAttrVarQueueBeyond(_) |
+ &Instruction::CallGetBValue(_) |
+ &Instruction::CallGetContinuationChunk(_) |
+ &Instruction::CallGetNextDBRef(_) |
+ &Instruction::CallGetNextOpDBRef(_) |
+ &Instruction::CallIsPartialString(_) |
+ &Instruction::CallHalt(_) |
+ &Instruction::CallGetLiftedHeapFromOffset(_) |
+ &Instruction::CallGetLiftedHeapFromOffsetDiff(_) |
+ &Instruction::CallGetSCCCleaner(_) |
+ &Instruction::CallHeadIsDynamic(_) |
+ &Instruction::CallInstallSCCCleaner(_) |
+ &Instruction::CallInstallInferenceCounter(_) |
+ &Instruction::CallLiftedHeapLength(_) |
+ &Instruction::CallLoadLibraryAsStream(_) |
+ &Instruction::CallModuleExists(_) |
+ &Instruction::CallNextEP(_) |
+ &Instruction::CallNoSuchPredicate(_) |
+ &Instruction::CallNumberToChars(_) |
+ &Instruction::CallNumberToCodes(_) |
+ &Instruction::CallOpDeclaration(_) |
+ &Instruction::CallOpen(_) |
+ &Instruction::CallSetStreamOptions(_) |
+ &Instruction::CallNextStream(_) |
+ &Instruction::CallPartialStringTail(_) |
+ &Instruction::CallPeekByte(_) |
+ &Instruction::CallPeekChar(_) |
+ &Instruction::CallPeekCode(_) |
+ &Instruction::CallPointsToContinuationResetMarker(_) |
+ &Instruction::CallPutByte(_) |
+ &Instruction::CallPutChar(_) |
+ &Instruction::CallPutChars(_) |
+ &Instruction::CallPutCode(_) |
+ &Instruction::CallReadQueryTerm(_) |
+ &Instruction::CallReadTerm(_) |
+ &Instruction::CallRedoAttrVarBinding(_) |
+ &Instruction::CallRemoveCallPolicyCheck(_) |
+ &Instruction::CallRemoveInferenceCounter(_) |
+ &Instruction::CallResetContinuationMarker(_) |
+ &Instruction::CallRestoreCutPolicy(_) |
+ &Instruction::CallSetCutPoint(..) |
+ &Instruction::CallSetInput(_) |
+ &Instruction::CallSetOutput(_) |
+ &Instruction::CallStoreBacktrackableGlobalVar(_) |
+ &Instruction::CallStoreGlobalVar(_) |
+ &Instruction::CallStreamProperty(_) |
+ &Instruction::CallSetStreamPosition(_) |
+ &Instruction::CallInferenceLevel(_) |
+ &Instruction::CallCleanUpBlock(_) |
+ &Instruction::CallEraseBall(_) |
+ &Instruction::CallFail(_) |
+ &Instruction::CallGetBall(_) |
+ &Instruction::CallGetCurrentBlock(_) |
+ &Instruction::CallGetCutPoint(_) |
+ &Instruction::CallGetStaggeredCutPoint(_) |
+ &Instruction::CallGetDoubleQuotes(_) |
+ &Instruction::CallInstallNewBlock(_) |
+ &Instruction::CallMaybe(_) |
+ &Instruction::CallCpuNow(_) |
+ &Instruction::CallCurrentTime(_) |
+ &Instruction::CallQuotedToken(_) |
+ &Instruction::CallReadTermFromChars(_) |
+ &Instruction::CallResetBlock(_) |
+ &Instruction::CallReturnFromVerifyAttr(_) |
+ &Instruction::CallSetBall(_) |
+ &Instruction::CallSetCutPointByDefault(..) |
+ &Instruction::CallSetDoubleQuotes(_) |
+ &Instruction::CallSetSeed(_) |
+ &Instruction::CallSkipMaxList(_) |
+ &Instruction::CallSleep(_) |
+ &Instruction::CallSocketClientOpen(_) |
+ &Instruction::CallSocketServerOpen(_) |
+ &Instruction::CallSocketServerAccept(_) |
+ &Instruction::CallSocketServerClose(_) |
+ &Instruction::CallTLSAcceptClient(_) |
+ &Instruction::CallTLSClientConnect(_) |
+ &Instruction::CallSucceed(_) |
+ &Instruction::CallTermAttributedVariables(_) |
+ &Instruction::CallTermVariables(_) |
+ &Instruction::CallTermVariablesUnderMaxDepth(_) |
+ &Instruction::CallTruncateLiftedHeapTo(_) |
+ &Instruction::CallUnifyWithOccursCheck(_) |
+ &Instruction::CallUnwindEnvironments(_) |
+ &Instruction::CallUnwindStack(_) |
+ &Instruction::CallWAMInstructions(_) |
+ &Instruction::CallWriteTerm(_) |
+ &Instruction::CallWriteTermToChars(_) |
+ &Instruction::CallScryerPrologVersion(_) |
+ &Instruction::CallCryptoRandomByte(_) |
+ &Instruction::CallCryptoDataHash(_) |
+ &Instruction::CallCryptoDataHKDF(_) |
+ &Instruction::CallCryptoPasswordHash(_) |
+ &Instruction::CallCryptoDataEncrypt(_) |
+ &Instruction::CallCryptoDataDecrypt(_) |
+ &Instruction::CallCryptoCurveScalarMult(_) |
+ &Instruction::CallEd25519Sign(_) |
+ &Instruction::CallEd25519Verify(_) |
+ &Instruction::CallEd25519NewKeyPair(_) |
+ &Instruction::CallEd25519KeyPairPublicKey(_) |
+ &Instruction::CallCurve25519ScalarMult(_) |
+ &Instruction::CallFirstNonOctet(_) |
+ &Instruction::CallLoadHTML(_) |
+ &Instruction::CallLoadXML(_) |
+ &Instruction::CallGetEnv(_) |
+ &Instruction::CallSetEnv(_) |
+ &Instruction::CallUnsetEnv(_) |
+ &Instruction::CallShell(_) |
+ &Instruction::CallPID(_) |
+ &Instruction::CallCharsBase64(_) |
+ &Instruction::CallDevourWhitespace(_) |
+ &Instruction::CallIsSTOEnabled(_) |
+ &Instruction::CallSetSTOAsUnify(_) |
+ &Instruction::CallSetNSTOAsUnify(_) |
+ &Instruction::CallSetSTOWithErrorAsUnify(_) |
+ &Instruction::CallHomeDirectory(_) |
+ &Instruction::CallDebugHook(_) |
+ &Instruction::CallAddDiscontiguousPredicate(_) |
+ &Instruction::CallAddDynamicPredicate(_) |
+ &Instruction::CallAddMultifilePredicate(_) |
+ &Instruction::CallAddGoalExpansionClause(_) |
+ &Instruction::CallAddTermExpansionClause(_) |
+ &Instruction::CallAddInSituFilenameModule(_) |
+ &Instruction::CallClauseToEvacuable(_) |
+ &Instruction::CallScopedClauseToEvacuable(_) |
+ &Instruction::CallConcludeLoad(_) |
+ &Instruction::CallDeclareModule(_) |
+ &Instruction::CallLoadCompiledLibrary(_) |
+ &Instruction::CallLoadContextSource(_) |
+ &Instruction::CallLoadContextFile(_) |
+ &Instruction::CallLoadContextDirectory(_) |
+ &Instruction::CallLoadContextModule(_) |
+ &Instruction::CallLoadContextStream(_) |
+ &Instruction::CallPopLoadContext(_) |
+ &Instruction::CallPopLoadStatePayload(_) |
+ &Instruction::CallPushLoadContext(_) |
+ &Instruction::CallPushLoadStatePayload(_) |
+ &Instruction::CallUseModule(_) |
+ &Instruction::CallBuiltInProperty(_) |
+ &Instruction::CallMetaPredicateProperty(_) |
+ &Instruction::CallMultifileProperty(_) |
+ &Instruction::CallDiscontiguousProperty(_) |
+ &Instruction::CallDynamicProperty(_) |
+ &Instruction::CallAbolishClause(_) |
+ &Instruction::CallAsserta(_) |
+ &Instruction::CallAssertz(_) |
+ &Instruction::CallRetract(_) |
+ &Instruction::CallIsConsistentWithTermQueue(_) |
+ &Instruction::CallFlushTermQueue(_) |
+ &Instruction::CallRemoveModuleExports(_) |
+ &Instruction::CallAddNonCountedBacktracking(_) |
+ &Instruction::CallPopCount(_) => {
+ let (name, arity) = self.to_name_and_arity();
+ functor!(atom!("call"), [atom(name), fixnum(arity)])
+ }
+ //
+ &Instruction::ExecuteAtomChars(_) |
+ &Instruction::ExecuteAtomCodes(_) |
+ &Instruction::ExecuteAtomLength(_) |
+ &Instruction::ExecuteBindFromRegister(_) |
+ &Instruction::ExecuteContinuation(_) |
+ &Instruction::ExecuteCharCode(_) |
+ &Instruction::ExecuteCharType(_) |
+ &Instruction::ExecuteCharsToNumber(_) |
+ &Instruction::ExecuteCodesToNumber(_) |
+ &Instruction::ExecuteCopyTermWithoutAttrVars(_) |
+ &Instruction::ExecuteCheckCutPoint(_) |
+ &Instruction::ExecuteClose(_) |
+ &Instruction::ExecuteCopyToLiftedHeap(_) |
+ &Instruction::ExecuteCreatePartialString(_) |
+ &Instruction::ExecuteCurrentHostname(_) |
+ &Instruction::ExecuteCurrentInput(_) |
+ &Instruction::ExecuteCurrentOutput(_) |
+ &Instruction::ExecuteDirectoryFiles(_) |
+ &Instruction::ExecuteFileSize(_) |
+ &Instruction::ExecuteFileExists(_) |
+ &Instruction::ExecuteDirectoryExists(_) |
+ &Instruction::ExecuteDirectorySeparator(_) |
+ &Instruction::ExecuteMakeDirectory(_) |
+ &Instruction::ExecuteMakeDirectoryPath(_) |
+ &Instruction::ExecuteDeleteFile(_) |
+ &Instruction::ExecuteRenameFile(_) |
+ &Instruction::ExecuteWorkingDirectory(_) |
+ &Instruction::ExecuteDeleteDirectory(_) |
+ &Instruction::ExecutePathCanonical(_) |
+ &Instruction::ExecuteFileTime(_) |
+ &Instruction::ExecuteDeleteAttribute(_) |
+ &Instruction::ExecuteDeleteHeadAttribute(_) |
+ &Instruction::ExecuteDynamicModuleResolution(_, _) |
+ &Instruction::ExecuteEnqueueAttributedVar(_) |
+ &Instruction::ExecuteFetchGlobalVar(_) |
+ &Instruction::ExecuteFirstStream(_) |
+ &Instruction::ExecuteFlushOutput(_) |
+ &Instruction::ExecuteGetByte(_) |
+ &Instruction::ExecuteGetChar(_) |
+ &Instruction::ExecuteGetNChars(_) |
+ &Instruction::ExecuteGetCode(_) |
+ &Instruction::ExecuteGetSingleChar(_) |
+ &Instruction::ExecuteResetAttrVarState(_) |
+ &Instruction::ExecuteTruncateIfNoLiftedHeapGrowthDiff(_) |
+ &Instruction::ExecuteTruncateIfNoLiftedHeapGrowth(_) |
+ &Instruction::ExecuteGetAttributedVariableList(_) |
+ &Instruction::ExecuteGetAttrVarQueueDelimiter(_) |
+ &Instruction::ExecuteGetAttrVarQueueBeyond(_) |
+ &Instruction::ExecuteGetBValue(_) |
+ &Instruction::ExecuteGetContinuationChunk(_) |
+ &Instruction::ExecuteGetNextDBRef(_) |
+ &Instruction::ExecuteGetNextOpDBRef(_) |
+ &Instruction::ExecuteIsPartialString(_) |
+ &Instruction::ExecuteHalt(_) |
+ &Instruction::ExecuteGetLiftedHeapFromOffset(_) |
+ &Instruction::ExecuteGetLiftedHeapFromOffsetDiff(_) |
+ &Instruction::ExecuteGetSCCCleaner(_) |
+ &Instruction::ExecuteHeadIsDynamic(_) |
+ &Instruction::ExecuteInstallSCCCleaner(_) |
+ &Instruction::ExecuteInstallInferenceCounter(_) |
+ &Instruction::ExecuteLiftedHeapLength(_) |
+ &Instruction::ExecuteLoadLibraryAsStream(_) |
+ &Instruction::ExecuteModuleExists(_) |
+ &Instruction::ExecuteNextEP(_) |
+ &Instruction::ExecuteNoSuchPredicate(_) |
+ &Instruction::ExecuteNumberToChars(_) |
+ &Instruction::ExecuteNumberToCodes(_) |
+ &Instruction::ExecuteOpDeclaration(_) |
+ &Instruction::ExecuteOpen(_) |
+ &Instruction::ExecuteSetStreamOptions(_) |
+ &Instruction::ExecuteNextStream(_) |
+ &Instruction::ExecutePartialStringTail(_) |
+ &Instruction::ExecutePeekByte(_) |
+ &Instruction::ExecutePeekChar(_) |
+ &Instruction::ExecutePeekCode(_) |
+ &Instruction::ExecutePointsToContinuationResetMarker(_) |
+ &Instruction::ExecutePutByte(_) |
+ &Instruction::ExecutePutChar(_) |
+ &Instruction::ExecutePutChars(_) |
+ &Instruction::ExecutePutCode(_) |
+ &Instruction::ExecuteReadQueryTerm(_) |
+ &Instruction::ExecuteReadTerm(_) |
+ &Instruction::ExecuteRedoAttrVarBinding(_) |
+ &Instruction::ExecuteRemoveCallPolicyCheck(_) |
+ &Instruction::ExecuteRemoveInferenceCounter(_) |
+ &Instruction::ExecuteResetContinuationMarker(_) |
+ &Instruction::ExecuteRestoreCutPolicy(_) |
+ &Instruction::ExecuteSetCutPoint(_, _) |
+ &Instruction::ExecuteSetInput(_) |
+ &Instruction::ExecuteSetOutput(_) |
+ &Instruction::ExecuteStoreBacktrackableGlobalVar(_) |
+ &Instruction::ExecuteStoreGlobalVar(_) |
+ &Instruction::ExecuteStreamProperty(_) |
+ &Instruction::ExecuteSetStreamPosition(_) |
+ &Instruction::ExecuteInferenceLevel(_) |
+ &Instruction::ExecuteCleanUpBlock(_) |
+ &Instruction::ExecuteEraseBall(_) |
+ &Instruction::ExecuteFail(_) |
+ &Instruction::ExecuteGetBall(_) |
+ &Instruction::ExecuteGetCurrentBlock(_) |
+ &Instruction::ExecuteGetCutPoint(_) |
+ &Instruction::ExecuteGetStaggeredCutPoint(_) |
+ &Instruction::ExecuteGetDoubleQuotes(_) |
+ &Instruction::ExecuteInstallNewBlock(_) |
+ &Instruction::ExecuteMaybe(_) |
+ &Instruction::ExecuteCpuNow(_) |
+ &Instruction::ExecuteCurrentTime(_) |
+ &Instruction::ExecuteQuotedToken(_) |
+ &Instruction::ExecuteReadTermFromChars(_) |
+ &Instruction::ExecuteResetBlock(_) |
+ &Instruction::ExecuteReturnFromVerifyAttr(_) |
+ &Instruction::ExecuteSetBall(_) |
+ &Instruction::ExecuteSetCutPointByDefault(_, _) |
+ &Instruction::ExecuteSetDoubleQuotes(_) |
+ &Instruction::ExecuteSetSeed(_) |
+ &Instruction::ExecuteSkipMaxList(_) |
+ &Instruction::ExecuteSleep(_) |
+ &Instruction::ExecuteSocketClientOpen(_) |
+ &Instruction::ExecuteSocketServerOpen(_) |
+ &Instruction::ExecuteSocketServerAccept(_) |
+ &Instruction::ExecuteSocketServerClose(_) |
+ &Instruction::ExecuteTLSAcceptClient(_) |
+ &Instruction::ExecuteTLSClientConnect(_) |
+ &Instruction::ExecuteSucceed(_) |
+ &Instruction::ExecuteTermAttributedVariables(_) |
+ &Instruction::ExecuteTermVariables(_) |
+ &Instruction::ExecuteTermVariablesUnderMaxDepth(_) |
+ &Instruction::ExecuteTruncateLiftedHeapTo(_) |
+ &Instruction::ExecuteUnifyWithOccursCheck(_) |
+ &Instruction::ExecuteUnwindEnvironments(_) |
+ &Instruction::ExecuteUnwindStack(_) |
+ &Instruction::ExecuteWAMInstructions(_) |
+ &Instruction::ExecuteWriteTerm(_) |
+ &Instruction::ExecuteWriteTermToChars(_) |
+ &Instruction::ExecuteScryerPrologVersion(_) |
+ &Instruction::ExecuteCryptoRandomByte(_) |
+ &Instruction::ExecuteCryptoDataHash(_) |
+ &Instruction::ExecuteCryptoDataHKDF(_) |
+ &Instruction::ExecuteCryptoPasswordHash(_) |
+ &Instruction::ExecuteCryptoDataEncrypt(_) |
+ &Instruction::ExecuteCryptoDataDecrypt(_) |
+ &Instruction::ExecuteCryptoCurveScalarMult(_) |
+ &Instruction::ExecuteEd25519Sign(_) |
+ &Instruction::ExecuteEd25519Verify(_) |
+ &Instruction::ExecuteEd25519NewKeyPair(_) |
+ &Instruction::ExecuteEd25519KeyPairPublicKey(_) |
+ &Instruction::ExecuteCurve25519ScalarMult(_) |
+ &Instruction::ExecuteFirstNonOctet(_) |
+ &Instruction::ExecuteLoadHTML(_) |
+ &Instruction::ExecuteLoadXML(_) |
+ &Instruction::ExecuteGetEnv(_) |
+ &Instruction::ExecuteSetEnv(_) |
+ &Instruction::ExecuteUnsetEnv(_) |
+ &Instruction::ExecuteShell(_) |
+ &Instruction::ExecutePID(_) |
+ &Instruction::ExecuteCharsBase64(_) |
+ &Instruction::ExecuteDevourWhitespace(_) |
+ &Instruction::ExecuteIsSTOEnabled(_) |
+ &Instruction::ExecuteSetSTOAsUnify(_) |
+ &Instruction::ExecuteSetNSTOAsUnify(_) |
+ &Instruction::ExecuteSetSTOWithErrorAsUnify(_) |
+ &Instruction::ExecuteHomeDirectory(_) |
+ &Instruction::ExecuteDebugHook(_) |
+ &Instruction::ExecuteAddDiscontiguousPredicate(_) |
+ &Instruction::ExecuteAddDynamicPredicate(_) |
+ &Instruction::ExecuteAddMultifilePredicate(_) |
+ &Instruction::ExecuteAddGoalExpansionClause(_) |
+ &Instruction::ExecuteAddTermExpansionClause(_) |
+ &Instruction::ExecuteAddInSituFilenameModule(_) |
+ &Instruction::ExecuteClauseToEvacuable(_) |
+ &Instruction::ExecuteScopedClauseToEvacuable(_) |
+ &Instruction::ExecuteConcludeLoad(_) |
+ &Instruction::ExecuteDeclareModule(_) |
+ &Instruction::ExecuteLoadCompiledLibrary(_) |
+ &Instruction::ExecuteLoadContextSource(_) |
+ &Instruction::ExecuteLoadContextFile(_) |
+ &Instruction::ExecuteLoadContextDirectory(_) |
+ &Instruction::ExecuteLoadContextModule(_) |
+ &Instruction::ExecuteLoadContextStream(_) |
+ &Instruction::ExecutePopLoadContext(_) |
+ &Instruction::ExecutePopLoadStatePayload(_) |
+ &Instruction::ExecutePushLoadContext(_) |
+ &Instruction::ExecutePushLoadStatePayload(_) |
+ &Instruction::ExecuteUseModule(_) |
+ &Instruction::ExecuteBuiltInProperty(_) |
+ &Instruction::ExecuteMetaPredicateProperty(_) |
+ &Instruction::ExecuteMultifileProperty(_) |
+ &Instruction::ExecuteDiscontiguousProperty(_) |
+ &Instruction::ExecuteDynamicProperty(_) |
+ &Instruction::ExecuteAbolishClause(_) |
+ &Instruction::ExecuteAsserta(_) |
+ &Instruction::ExecuteAssertz(_) |
+ &Instruction::ExecuteRetract(_) |
+ &Instruction::ExecuteIsConsistentWithTermQueue(_) |
+ &Instruction::ExecuteFlushTermQueue(_) |
+ &Instruction::ExecuteRemoveModuleExports(_) |
+ &Instruction::ExecuteAddNonCountedBacktracking(_) |
+ &Instruction::ExecutePopCount(_) => {
+ let (name, arity) = self.to_name_and_arity();
+ functor!(atom!("execute"), [atom(name), fixnum(arity)])
+ }
+ //
+ &Instruction::Deallocate => {
+ functor!(atom!("deallocate"))
+ }
+ &Instruction::JmpByCall(_, offset, ..) => {
+ functor!(atom!("jmp_by_call"), [fixnum(offset)])
+ }
+ &Instruction::JmpByExecute(_, offset, ..) => {
+ functor!(atom!("jmp_by_execute"), [fixnum(offset)])
+ }
+ &Instruction::RevJmpBy(offset) => {
+ functor!(atom!("rev_jmp_by"), [fixnum(offset)])
+ }
+ &Instruction::Proceed => {
+ functor!(atom!("proceed"))
+ }
+ &Instruction::GetConstant(lvl, c, r) => {
+ let lvl_stub = lvl.into_functor();
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ atom!("get_constant"),
+ [str(h, 0), cell(c), str(h, 1)],
+ [lvl_stub, rt_stub]
+ )
+ }
+ &Instruction::GetList(lvl, r) => {
+ let lvl_stub = lvl.into_functor();
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ atom!("get_list"),
+ [str(h, 0), str(h, 1)],
+ [lvl_stub, rt_stub]
+ )
+ }
+ &Instruction::GetPartialString(lvl, s, r, has_tail) => {
+ let lvl_stub = lvl.into_functor();
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ atom!("get_partial_string"),
+ [
+ str(h, 0),
+ string(h, s),
+ str(h, 1),
+ boolean(has_tail)
+ ],
+ [lvl_stub, rt_stub]
+ )
+ }
+ &Instruction::GetStructure(name, arity, r) => {
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ atom!("get_structure"),
+ [atom(name), fixnum(arity), str(h, 0)],
+ [rt_stub]
+ )
+ }
+ &Instruction::GetValue(r, arg) => {
+ let rt_stub = reg_type_into_functor(r);
+ functor!(atom!("get_value"), [str(h, 0), fixnum(arg)], [rt_stub])
+ }
+ &Instruction::GetVariable(r, arg) => {
+ let rt_stub = reg_type_into_functor(r);
+ functor!(atom!("get_variable"), [str(h, 0), fixnum(arg)], [rt_stub])
+ }
+ &Instruction::UnifyConstant(c) => {
+ functor!(atom!("unify_constant"), [cell(c)])
+ }
+ &Instruction::UnifyLocalValue(r) => {
+ let rt_stub = reg_type_into_functor(r);
+ functor!(atom!("unify_local_value"), [str(h, 0)], [rt_stub])
+ }
+ &Instruction::UnifyVariable(r) => {
+ let rt_stub = reg_type_into_functor(r);
+ functor!(atom!("unify_variable"), [str(h, 0)], [rt_stub])
+ }
+ &Instruction::UnifyValue(r) => {
+ let rt_stub = reg_type_into_functor(r);
+ functor!(atom!("unify_value"), [str(h, 0)], [rt_stub])
+ }
+ &Instruction::UnifyVoid(vars) => {
+ functor!(atom!("unify_void"), [fixnum(vars)])
+ }
+ &Instruction::PutUnsafeValue(norm, arg) => {
+ functor!(atom!("put_unsafe_value"), [fixnum(norm), fixnum(arg)])
+ }
+ &Instruction::PutConstant(lvl, c, r) => {
+ let lvl_stub = lvl.into_functor();
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ atom!("put_constant"),
+ [str(h, 0), cell(c), str(h, 1)],
+ [lvl_stub, rt_stub]
+ )
+ }
+ &Instruction::PutList(lvl, r) => {
+ let lvl_stub = lvl.into_functor();
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ atom!("put_list"),
+ [str(h, 0), str(h, 1)],
+ [lvl_stub, rt_stub]
+ )
+ }
+ &Instruction::PutPartialString(lvl, s, r, has_tail) => {
+ let lvl_stub = lvl.into_functor();
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ atom!("put_partial_string"),
+ [
+ str(h, 0),
+ string(h, s),
+ str(h, 1),
+ boolean(has_tail)
+ ],
+ [lvl_stub, rt_stub]
+ )
+ }
+ &Instruction::PutStructure(name, arity, r) => {
+ let rt_stub = reg_type_into_functor(r);
+
+ functor!(
+ atom!("put_structure"),
+ [atom(name), fixnum(arity), str(h, 0)],
+ [rt_stub]
+ )
+ }
+ &Instruction::PutValue(r, arg) => {
+ let rt_stub = reg_type_into_functor(r);
+ functor!(atom!("put_value"), [str(h, 0), fixnum(arg)], [rt_stub])
+ }
+ &Instruction::PutVariable(r, arg) => {
+ let rt_stub = reg_type_into_functor(r);
+ functor!(atom!("put_variable"), [str(h, 0), fixnum(arg)], [rt_stub])
+ }
+ &Instruction::SetConstant(c) => {
+ functor!(atom!("set_constant"), [cell(c)])
+ }
+ &Instruction::SetLocalValue(r) => {
+ let rt_stub = reg_type_into_functor(r);
+ functor!(atom!("set_local_value"), [str(h, 0)], [rt_stub])
+ }
+ &Instruction::SetVariable(r) => {
+ let rt_stub = reg_type_into_functor(r);
+ functor!(atom!("set_variable"), [str(h, 0)], [rt_stub])
+ }
+ &Instruction::SetValue(r) => {
+ let rt_stub = reg_type_into_functor(r);
+ functor!(atom!("set_value"), [str(h, 0)], [rt_stub])
+ }
+ &Instruction::SetVoid(vars) => {
+ functor!(atom!("set_void"), [fixnum(vars)])
+ }
+ &Instruction::BreakFromDispatchLoop => {
+ functor!(atom!("$break_from_dispatch_loop"))
+ }
+ }
+ }
+ }
+ }
+}
+
+pub fn generate_instructions_rs() -> TokenStream {
+ let input = InstructionTemplate::to_derive_input();
+ let mut instr_data = InstructionData::new();
+
+ instr_data.generate_instruction_enum_loop(input);
+
+ let instr_variants: Vec<_> = instr_data.instr_variants
+ .iter()
+ .cloned()
+ .map(|(_, _, _, variant)| variant)
+ .collect();
+
+ fn attributeless_enum<T: ToDeriveInput>() -> Vec<Variant> {
+ if let Data::Enum(DataEnum { mut variants, .. }) = T::to_derive_input().data {
+ for variant in &mut variants {
+ variant.attrs.clear();
+ }
+
+ variants.into_iter().collect()
+ } else {
+ unreachable!()
+ }
+ }
+
+ let clause_type_variants = attributeless_enum::<ClauseType>();
+ let builtin_type_variants = attributeless_enum::<BuiltInClauseType>();
+ let inlined_type_variants = attributeless_enum::<InlinedClauseType>();
+ let system_clause_type_variants = attributeless_enum::<SystemClauseType>();
+ let repl_code_ptr_variants = attributeless_enum::<REPLCodePtr>();
+ let compare_number_variants = attributeless_enum::<CompareNumber>();
+ let compare_term_variants = attributeless_enum::<CompareTerm>();
+
+ let mut clause_type_from_name_and_arity_arms = vec![];
+ let mut clause_type_to_instr_arms = vec![];
+ let mut clause_type_name_arms = vec![];
+
+ for (name, arity, variant) in instr_data.compare_number_variants {
+ let ident = variant.ident.clone();
+
+ let variant_fields: Vec<_> = variant.fields
+ .into_iter()
+ .map(|field| {
+ let ty = field.ty;
+ quote! { #ty::default() }
+ })
+ .collect();
+
+ clause_type_from_name_and_arity_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::Inlined(
+ InlinedClauseType::CompareNumber(CompareNumber::#ident(#(#variant_fields),*))
+ )
+ }
+ } else {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::Inlined(
+ InlinedClauseType::CompareNumber(CompareNumber::#ident)
+ )
+ }
+ });
+
+ clause_type_name_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ ClauseType::Inlined(
+ InlinedClauseType::CompareNumber(CompareNumber::#ident(..))
+ ) => atom!(#name)
+ }
+ } else {
+ quote! {
+ ClauseType::Inlined(
+ InlinedClauseType::CompareNumber(CompareNumber::#ident)
+ ) => (atom!(#name), #arity)
+ }
+ });
+
+ let ident = variant.ident;
+ let instr_ident = format_ident!("Call{}", ident);
+
+ let placeholder_ids: Vec<_> = (0 .. variant_fields.len())
+ .map(|n| format_ident!("f_{}", n))
+ .collect();
+
+ clause_type_to_instr_arms.push(
+ quote! {
+ ClauseType::Inlined(
+ InlinedClauseType::CompareNumber(CompareNumber::#ident(#(#placeholder_ids),*))
+ ) => Instruction::#instr_ident(#(#placeholder_ids),*, 0)
+ }
+ );
+ }
+
+ for (name, arity, variant) in instr_data.compare_term_variants {
+ let ident = variant.ident.clone();
+
+ clause_type_from_name_and_arity_arms.push(quote! {
+ (atom!(#name), #arity) => ClauseType::BuiltIn(
+ BuiltInClauseType::CompareTerm(CompareTerm::#ident)
+ )
+ });
+
+ clause_type_name_arms.push(
+ quote! {
+ ClauseType::BuiltIn(
+ BuiltInClauseType::CompareTerm(CompareTerm::#ident)
+ ) => atom!(#name)
+ }
+ );
+
+ let ident = variant.ident;
+ let instr_ident = format_ident!("Call{}", ident);
+
+ clause_type_to_instr_arms.push(
+ quote! {
+ ClauseType::BuiltIn(
+ BuiltInClauseType::CompareTerm(CompareTerm::#ident)
+ ) => Instruction::#instr_ident(0)
+ }
+ );
+ }
+
+ for (name, arity, variant) in instr_data.builtin_type_variants {
+ let ident = variant.ident.clone();
+
+ let variant_fields: Vec<_> = variant.fields
+ .into_iter()
+ .map(|field| {
+ let ty = field.ty;
+ quote! { #ty::default() }
+ })
+ .collect();
+
+ clause_type_from_name_and_arity_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::BuiltIn(
+ BuiltInClauseType::#ident(#(#variant_fields),*)
+ )
+ }
+ } else {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::BuiltIn(
+ BuiltInClauseType::#ident
+ )
+ }
+ });
+
+ clause_type_name_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ ClauseType::BuiltIn(
+ BuiltInClauseType::#ident(..)
+ ) => atom!(#name)
+ }
+ } else {
+ quote! {
+ ClauseType::BuiltIn(
+ BuiltInClauseType::#ident
+ ) => atom!(#name)
+ }
+ });
+
+ let ident = variant.ident;
+ let instr_ident = format_ident!("Call{}", ident);
+
+ let placeholder_ids: Vec<_> = (0 .. variant_fields.len())
+ .map(|n| format_ident!("f_{}", n))
+ .collect();
+
+ clause_type_to_instr_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ ClauseType::BuiltIn(
+ BuiltInClauseType::#ident(#(#placeholder_ids),*)
+ ) => Instruction::#instr_ident(#(#placeholder_ids),*,0)
+ }
+ } else {
+ quote! {
+ ClauseType::BuiltIn(
+ BuiltInClauseType::#ident
+ ) => Instruction::#instr_ident(0)
+ }
+ });
+ }
+
+ for (name, arity, variant) in instr_data.inlined_type_variants {
+ let ident = variant.ident.clone();
+
+ let variant_fields: Vec<_> = variant.fields
+ .into_iter()
+ .map(|field| {
+ if field.ty.type_id() == TypeId::of::<usize>() {
+ quote! { #arity }
+ } else {
+ let ty = field.ty;
+ quote! { #ty::default() }
+ }
+ })
+ .collect();
+
+ clause_type_from_name_and_arity_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::Inlined(
+ InlinedClauseType::#ident(#(#variant_fields),*)
+ )
+ }
+ } else {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::Inlined(
+ InlinedClauseType::#ident
+ )
+ }
+ });
+
+ clause_type_name_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ ClauseType::Inlined(
+ InlinedClauseType::#ident(..)
+ ) => atom!(#name)
+ }
+ } else {
+ quote! {
+ ClauseType::Inlined(
+ InlinedClauseType::#ident
+ ) => atom!(#name)
+ }
+ });
+
+ let ident = variant.ident;
+ let instr_ident = format_ident!("Call{}", ident);
+
+ let placeholder_ids: Vec<_> = (0 .. variant_fields.len())
+ .map(|n| format_ident!("f_{}", n))
+ .collect();
+
+ clause_type_to_instr_arms.push(
+ quote! {
+ ClauseType::Inlined(
+ InlinedClauseType::#ident(#(#placeholder_ids),*)
+ ) => Instruction::#instr_ident(#(#placeholder_ids),*,0)
+ }
+ );
+ }
+
+ for (name, arity, variant) in instr_data.system_clause_type_variants {
+ let ident = variant.ident.clone();
+
+ let variant_fields: Vec<_> = variant.fields
+ .into_iter()
+ .map(|field| {
+ if field.ty == parse_quote! { usize } {
+ quote! { #arity }
+ } else {
+ let ty = field.ty;
+ quote! { #ty::default() }
+ }
+ })
+ .collect();
+
+ clause_type_from_name_and_arity_arms.push(if !variant_fields.is_empty() {
+ if ident.to_string() == "SetCutPoint" {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::System(
+ SystemClauseType::#ident(temp_v!(1))
+ )
+ }
+ } else if ident.to_string() == "SetCutPointByDefault" {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::System(
+ SystemClauseType::#ident(temp_v!(1))
+ )
+ }
+ } else {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::System(
+ SystemClauseType::#ident(#(#variant_fields),*)
+ )
+ }
+ }
+ } else {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::System(
+ SystemClauseType::#ident
+ )
+ }
+ });
+
+ clause_type_name_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ ClauseType::System(
+ SystemClauseType::#ident(..)
+ ) => atom!(#name)
+ }
+ } else {
+ quote! {
+ ClauseType::System(
+ SystemClauseType::#ident
+ ) => atom!(#name)
+ }
+ });
+
+ let ident = variant.ident;
+ let instr_ident = if ident != "CallContinuation" {
+ format_ident!("Call{}", ident)
+ } else {
+ ident.clone()
+ };
+
+ let placeholder_ids: Vec<_> = (0 .. variant_fields.len())
+ .map(|n| format_ident!("f_{}", n))
+ .collect();
+
+ clause_type_to_instr_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ ClauseType::System(
+ SystemClauseType::#ident(#(#placeholder_ids),*)
+ ) => Instruction::#instr_ident(#(#placeholder_ids),*,0)
+ }
+ } else {
+ quote! {
+ ClauseType::System(
+ SystemClauseType::#ident
+ ) => Instruction::#instr_ident(0)
+ }
+ });
+ }
+
+ for (name, arity, variant) in instr_data.repl_code_ptr_variants {
+ let ident = variant.ident.clone();
+
+ let variant_fields: Vec<_> = variant.fields
+ .into_iter()
+ .map(|field| {
+ if field.ty.type_id() == TypeId::of::<usize>() {
+ quote! { #arity }
+ } else {
+ let ty = field.ty;
+ quote! { #ty::default() }
+ }
+ })
+ .collect();
+
+ clause_type_from_name_and_arity_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::System(SystemClauseType::REPL(
+ REPLCodePtr::#ident(#(#variant_fields),*)
+ ))
+ }
+ } else {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::System(SystemClauseType::REPL(
+ REPLCodePtr::#ident
+ ))
+ }
+ });
+
+ clause_type_name_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ ClauseType::System(
+ SystemClauseType::REPL(REPLCodePtr::#ident(..))
+ ) => atom!(#name)
+ }
+ } else {
+ quote! {
+ ClauseType::System(
+ SystemClauseType::REPL(REPLCodePtr::#ident)
+ ) => atom!(#name)
+ }
+ });
+
+ let ident = variant.ident;
+ let instr_ident = format_ident!("Call{}", ident);
+
+ let placeholder_ids: Vec<_> = (0 .. variant_fields.len())
+ .map(|n| format_ident!("f_{}", n))
+ .collect();
+
+ clause_type_to_instr_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ ClauseType::System(SystemClauseType::REPL(
+ REPLCodePtr::#ident(#(#placeholder_ids),*)
+ )) => Instruction::#instr_ident(#(#placeholder_ids),*,0)
+ }
+ } else {
+ quote! {
+ ClauseType::System(SystemClauseType::REPL(
+ REPLCodePtr::#ident
+ )) => Instruction::#instr_ident(0)
+ }
+ });
+ }
+
+ for (name, arity, variant) in instr_data.clause_type_variants {
+ let ident = variant.ident.clone();
+
+ if ident == "Named" {
+ clause_type_from_name_and_arity_arms.push(quote! {
+ (name, arity) => ClauseType::Named(arity, name, CodeIndex::default())
+ });
+
+ clause_type_to_instr_arms.push(quote! {
+ ClauseType::Named(arity, name, idx) => Instruction::CallNamed(arity, name, idx, 0)
+ });
+
+ clause_type_name_arms.push(quote! {
+ ClauseType::Named(_, name, _) => *name
+ });
+
+ continue;
+ }
+
+ let variant_fields: Vec<_> = variant.fields
+ .into_iter()
+ .map(|field| {
+ if field.ty == parse_quote! { usize } {
+ quote! { #arity }
+ } else {
+ let ty = field.ty;
+ quote! { #ty::default() }
+ }
+ })
+ .collect();
+
+ clause_type_from_name_and_arity_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::#ident(#(#variant_fields),*)
+ }
+ } else {
+ quote! {
+ (atom!(#name), #arity) => ClauseType::#ident
+ }
+ });
+
+ clause_type_name_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ ClauseType::#ident(..) => atom!(#name)
+ }
+ } else {
+ quote! {
+ ClauseType::#ident => atom!(#name)
+ }
+ });
+
+ let ident = variant.ident;
+
+ let placeholder_ids: Vec<_> = (0 .. variant_fields.len())
+ .map(|n| format_ident!("f_{}", n))
+ .collect();
+
+ clause_type_to_instr_arms.push(if !variant_fields.is_empty() {
+ quote! {
+ ClauseType::#ident(#(#placeholder_ids),*) =>
+ Instruction::#ident(#(#placeholder_ids),*,0)
+ }
+ } else {
+ quote! {
+ ClauseType::#ident => Instruction::#ident(0)
+ }
+ });
+ }
+
+ let to_execute_arms: Vec<_> = instr_data.instr_variants
+ .iter()
+ .cloned()
+ .filter_map(|(_, _, _, variant)| {
+ let variant_ident = variant.ident.clone();
+ let variant_string = variant.ident.to_string();
+
+ let enum_arity = if let Fields::Unnamed(fields) = &variant.fields {
+ fields.unnamed.len()
+ } else {
+ 0
+ };
+
+ let placeholder_ids: Vec<_> = (0 .. enum_arity)
+ .map(|n| format_ident!("f_{}", n))
+ .collect();
+
+ if variant_string.starts_with("Call") {
+ let execute_ident = format_ident!("Execute{}", variant_string["Call".len() ..]);
+
+ Some(if enum_arity == 0 {
+ quote! {
+ Instruction::#variant_ident =>
+ Instruction::#execute_ident
+ }
+ } else {
+ quote! {
+ Instruction::#variant_ident(#(#placeholder_ids),*) =>
+ Instruction::#execute_ident(#(#placeholder_ids),*)
+ }
+ })
+ } else if variant_string.starts_with("DefaultCall") {
+ let execute_ident =
+ format_ident!("DefaultExecute{}", variant_string["DefaultCall".len() ..]);
+
+ Some(if enum_arity == 0 {
+ quote! {
+ Instruction::#variant_ident =>
+ Instruction::#execute_ident
+ }
+ } else {
+ quote! {
+ Instruction::#variant_ident(#(#placeholder_ids),*) =>
+ Instruction::#execute_ident(#(#placeholder_ids),*)
+ }
+ })
+ } else if variant_string == "JmpByCall" {
+ Some(quote! {
+ Instruction::JmpByCall(#(#placeholder_ids),*) =>
+ Instruction::JmpByExecute(#(#placeholder_ids),*)
+ })
+ } else {
+ None
+ }
+ })
+ .collect();
+
+ let is_execute_arms: Vec<_> = instr_data.instr_variants
+ .iter()
+ .cloned()
+ .filter_map(|(_, _, _, variant)| {
+ let variant_ident = variant.ident.clone();
+ let variant_string = variant.ident.to_string();
+
+ let enum_arity = if let Fields::Unnamed(fields) = &variant.fields {
+ fields.unnamed.len()
+ } else {
+ 0
+ };
+
+ if variant_string.starts_with("Execute") {
+ Some(if enum_arity == 0 {
+ quote! {
+ Instruction::#variant_ident => true
+ }
+ } else {
+ quote! {
+ Instruction::#variant_ident(..) => true
+ }
+ })
+ } else if variant_string.starts_with("DefaultExecute") {
+ Some(if enum_arity == 0 {
+ quote! {
+ Instruction::#variant_ident => true
+ }
+ } else {
+ quote! {
+ Instruction::#variant_ident(..) => true
+ }
+ })
+ } else if variant_string == "JmpByExecute" {
+ Some(quote! {
+ Instruction::#variant_ident(..) => true
+ })
+ } else {
+ None
+ }
+ })
+ .collect();
+
+ let to_default_arms: Vec<_> = instr_data.instr_variants
+ .iter()
+ .cloned()
+ .filter_map(|(_, _, countable_inference, variant)| {
+ if !is_non_default_callable(&variant.ident) {
+ return None;
+ }
+
+ if let CountableInference::HasDefault = countable_inference {
+ let variant_ident = variant.ident.clone();
+ let def_variant_ident = format_ident!("Default{}", variant.ident);
+ let enum_arity = if let Fields::Unnamed(fields) = &variant.fields {
+ fields.unnamed.len()
+ } else {
+ unreachable!()
+ };
+
+ let placeholder_ids: Vec<_> = (0 .. enum_arity)
+ .map(|n| format_ident!("f_{}", n))
+ .collect();
+
+ Some(quote! {
+ Instruction::#variant_ident(#(#placeholder_ids),*) =>
+ Instruction::#def_variant_ident(#(#placeholder_ids),*)
+ })
+ } else {
+ None
+ }
+ })
+ .collect();
+
+ let perm_vars_mut_arms: Vec<_> = instr_data.instr_variants
+ .iter()
+ .cloned()
+ .filter_map(|(_, _, _, variant)| {
+ if !is_callable(&variant.ident) && !is_jmp(&variant.ident) {
+ return None;
+ }
+
+ let variant_ident = variant.ident.clone();
+ let enum_arity = if let Fields::Unnamed(fields) = &variant.fields {
+ fields.unnamed.len()
+ } else {
+ 0
+ };
+
+ let placeholder_ids: Vec<_> = (1 .. enum_arity)
+ .map(|_| format_ident!("_"))
+ .collect();
+
+ Some(if enum_arity == 1 {
+ quote! {
+ Instruction::#variant_ident(ref mut perm_vars) => Some(perm_vars)
+ }
+ } else {
+ quote! {
+ Instruction::#variant_ident(#(#placeholder_ids),*, ref mut perm_vars) =>
+ Some(perm_vars)
+ }
+ })
+ })
+ .collect();
+
+ let control_flow_arms: Vec<_> = instr_data.instr_variants
+ .iter()
+ .cloned()
+ .filter_map(|(_, _, _, variant)| {
+ if !is_callable(&variant.ident) && !is_jmp(&variant.ident) {
+ return None;
+ }
+
+ let variant_ident = variant.ident.clone();
+
+ Some(quote! {
+ Instruction::#variant_ident(..) => true
+ })
+ })
+ .collect();
+
+ let instr_macro_arms: Vec<_> = instr_data.instr_variants
+ .iter()
+ .rev() // produce default, execute & default & execute cases first.
+ .cloned()
+ .filter_map(|(name, arity, _, variant)| {
+ let variant_ident = variant.ident.clone();
+ let variant_string = variant.ident.to_string();
+ let arity = match arity {
+ Arity::Static(arity) => arity,
+ _ => 1
+ };
+
+ Some(if variant_string.starts_with("Execute") {
+ quote! {
+ (#name, execute, $($args:expr),*) => {
+ Instruction::#variant_ident($($args),*)
+ }
+ }
+ } else if variant_string.starts_with("Call") {
+ quote! {
+ (#name, $($args:expr),*) => {
+ Instruction::#variant_ident($($args),*)
+ }
+ }
+ } else if variant_string.starts_with("DefaultExecute") {
+ quote! {
+ (#name, execute, default, $($args:expr),*) => {
+ Instruction::#variant_ident($($args),*)
+ }
+ }
+ } else if variant_string.starts_with("DefaultCall") {
+ quote! {
+ (#name, default, $($args:expr),*) => {
+ Instruction::#variant_ident($($args),*)
+ }
+ }
+ } else {
+ if arity == 0 {
+ quote! {
+ (#name) => {
+ Instruction::#variant_ident
+ }
+ }
+ } else {
+ quote! {
+ (#name, $($args:expr),*) => {
+ Instruction::#variant_ident($($args),*)
+ }
+ }
+ }
+ })
+ })
+ .collect();
+
+ let name_and_arity_arms: Vec<_> = instr_data.instr_variants
+ .into_iter()
+ .map(|(name,arity,_,variant)| {
+ let ident = &variant.ident;
+
+ let enum_arity = if let Fields::Unnamed(fields) = &variant.fields {
+ fields.unnamed.len()
+ } else {
+ 0
+ };
+
+ match arity {
+ Arity::Static(_) if enum_arity == 0 => {
+ quote! { &Instruction::#ident => (atom!(#name), #arity) }
+ }
+ Arity::Static(_) => {
+ quote! { &Instruction::#ident(..) => (atom!(#name), #arity) }
+ }
+ Arity::Ident(_) if enum_arity == 0 => {
+ quote! { &Instruction::#ident(#arity) => (atom!(#name), #arity) }
+ }
+ Arity::Ident(_) => {
+ quote! { &Instruction::#ident(#arity, ..) => (atom!(#name), #arity) }
+ }
+ }
+ })
+ .collect();
+
+ let preface_tokens = generate_instruction_preface();
+
+ quote! {
+ #preface_tokens
+
+ #[derive(Clone, Debug)]
+ pub enum CompareTerm {
+ #(
+ #compare_term_variants,
+ )*
+ }
+
+ #[derive(Clone, Copy, Debug)]
+ pub enum CompareNumber {
+ #(
+ #compare_number_variants,
+ )*
+ }
+
+ impl CompareNumber {
+ pub fn set_terms(&mut self, l_at_1: ArithmeticTerm, l_at_2: ArithmeticTerm) {
+ match self {
+ CompareNumber::NumberGreaterThan(ref mut at_1, ref mut at_2) |
+ CompareNumber::NumberLessThan(ref mut at_1, ref mut at_2) |
+ CompareNumber::NumberGreaterThanOrEqual(ref mut at_1, ref mut at_2) |
+ CompareNumber::NumberLessThanOrEqual(ref mut at_1, ref mut at_2) |
+ CompareNumber::NumberNotEqual(ref mut at_1, ref mut at_2) |
+ CompareNumber::NumberEqual(ref mut at_1, ref mut at_2) => {
+ *at_1 = l_at_1;
+ *at_2 = l_at_2;
+ }
+ }
+ }
+ }
+
+ #[derive(Clone, Debug)]
+ pub enum BuiltInClauseType {
+ #(
+ #builtin_type_variants,
+ )*
+ }
+
+ #[derive(Clone, Debug)]
+ pub enum InlinedClauseType {
+ #(
+ #inlined_type_variants,
+ )*
+ }
+
+ #[derive(Clone, Debug)]
+ pub enum SystemClauseType {
+ #(
+ #system_clause_type_variants,
+ )*
+ }
+
+ #[derive(Clone, Debug)]
+ pub enum REPLCodePtr {
+ #(
+ #repl_code_ptr_variants,
+ )*
+ }
+
+ #[derive(Clone, Debug)]
+ pub enum ClauseType {
+ #(
+ #clause_type_variants,
+ )*
+ }
+
+ impl ClauseType {
+ pub fn from(name: Atom, arity: usize) -> ClauseType {
+ match (name, arity) {
+ #(
+ #clause_type_from_name_and_arity_arms,
+ )*
+ }
+ }
+
+ pub fn to_instr(self) -> Instruction {
+ match self {
+ #(
+ #clause_type_to_instr_arms,
+ )*
+ }
+ }
+
+ pub fn is_builtin(&self) -> bool {
+ if let ClauseType::BuiltIn(_) = self {
+ true
+ } else {
+ false
+ }
+ }
+
+ pub fn is_inlined(&self) -> bool {
+ if let ClauseType::Inlined(_) = self {
+ true
+ } else {
+ false
+ }
+ }
+
+ pub fn name(&self) -> Atom {
+ match self {
+ #(
+ #clause_type_name_arms,
+ )*
+ }
+ }
+ }
+
+ #[derive(Clone, Debug)]
+ pub enum Instruction {
+ #(
+ #instr_variants,
+ )*
+ }
+
+ impl Instruction {
+ pub fn to_name_and_arity(&self) -> (Atom, usize) {
+ match self {
+ #(
+ #name_and_arity_arms,
+ )*
+ }
+ }
+
+ pub fn to_default(self) -> Instruction {
+ match self {
+ #(
+ #to_default_arms,
+ )*
+ _ => self,
+ }
+ }
+
+ pub fn to_execute(self) -> Instruction {
+ match self {
+ #(
+ #to_execute_arms,
+ )*
+ _ => self
+ }
+ }
+
+ pub fn is_execute(&self) -> bool {
+ match self {
+ #(
+ #is_execute_arms,
+ )*
+ _ => false,
+ }
+ }
+
+ pub fn perm_vars_mut(&mut self) -> Option<&mut usize> {
+ match self {
+ #(
+ #perm_vars_mut_arms,
+ )*
+ _ => None,
+ }
+ }
+
+ pub fn is_ctrl_instr(&self) -> bool {
+ match self {
+ &Instruction::Allocate(_) |
+ &Instruction::Deallocate |
+ &Instruction::Proceed |
+ &Instruction::RevJmpBy(_) => true,
+ #(
+ #control_flow_arms,
+ )*
+ _ => false,
+ }
+ }
+
+ pub fn is_query_instr(&self) -> bool {
+ match self {
+ &Instruction::GetVariable(..) |
+ &Instruction::PutConstant(..) |
+ &Instruction::PutList(..) |
+ &Instruction::PutPartialString(..) |
+ &Instruction::PutStructure(..) |
+ &Instruction::PutUnsafeValue(..) |
+ &Instruction::PutValue(..) |
+ &Instruction::PutVariable(..) |
+ &Instruction::SetConstant(..) |
+ &Instruction::SetLocalValue(..) |
+ &Instruction::SetVariable(..) |
+ &Instruction::SetValue(..) |
+ &Instruction::SetVoid(..) => true,
+ _ => false,
+ }
+ }
+ }
+
+ #[macro_export]
+ macro_rules! instr {
+ #(
+ #instr_macro_arms
+ );*
+ }
+ }
+}
+
+fn is_callable(id: &Ident) -> bool {
+ let id = id.to_string();
+
+ id.starts_with("Call") || id.starts_with("Execute") || id.starts_with("DefaultCall") ||
+ id.starts_with("DefaultExecute")
+}
+
+fn is_non_default_callable(id: &Ident) -> bool {
+ let id = id.to_string();
+ id.starts_with("Call") || id.starts_with("Execute")
+}
+
+fn is_jmp(id: &Ident) -> bool {
+ let id = id.to_string();
+ id.starts_with("JmpByCall") || id.starts_with("JmpByExecute")
+}
+
+fn create_instr_variant(id: Ident, mut variant: Variant) -> Variant {
+ use proc_macro2::Span;
+ use syn::punctuated::Punctuated;
+ use syn::token::Paren;
+
+ // add the perm_vars usize field to the variant.
+
+ if is_callable(&id) || is_jmp(&id) {
+ let field = Field {
+ attrs: vec![],
+ vis: Visibility::Inherited,
+ ident: None,
+ colon_token: None,
+ ty: parse_quote! { usize },
+ };
+
+ match &mut variant.fields {
+ Fields::Unnamed(ref mut fields) => {
+ fields.unnamed.push(field);
+ }
+ Fields::Unit => {
+ variant.fields = Fields::Unnamed(FieldsUnnamed {
+ paren_token: Paren(Span::call_site()),
+ unnamed: {
+ let mut fields_seq = Punctuated::new();
+ fields_seq.push(field);
+ fields_seq
+ }
+ });
+ }
+ _ => {
+ unreachable!();
+ }
+ }
+ }
+
+ variant.ident = id;
+ variant.attrs.clear();
+
+ variant
+}
+
+fn prop_from_ident<DiscriminantT>(id: &Ident, key: &'static str) -> &'static str
+ where DiscriminantT: FromStr + strum::EnumProperty + std::fmt::Debug
+{
+ let disc = match DiscriminantT::from_str(id.to_string().as_str()) {
+ Ok(disc) => disc,
+ Err(_) => {
+ panic!("can't generate discriminant {}", id);
+ }
+ };
+
+ match disc.get_str(key) {
+ Some(prop) => prop,
+ None => {
+ panic!("can't find property {} of discriminant {:?}", key, disc);
+ }
+ }
+}
+
+#[derive(Clone, Copy)]
+enum Arity {
+ Static(usize),
+ Ident(&'static str)
+}
+
+impl From<&'static str> for Arity {
+ fn from(arity: &'static str) -> Self {
+ usize::from_str_radix(&arity, 10)
+ .map(|n| Arity::Static(n))
+ .unwrap_or_else(|_| Arity::Ident(arity))
+ }
+}
+
+#[derive(Clone, Copy)]
+enum CountableInference {
+ HasDefault,
+ NotCounted,
+}
+
+struct InstructionData {
+ instr_variants: Vec<(&'static str, Arity, CountableInference, Variant)>,
+ clause_type_variants: Vec<(&'static str, Arity, Variant)>,
+ builtin_type_variants: Vec<(&'static str, Arity, Variant)>,
+ inlined_type_variants: Vec<(&'static str, Arity, Variant)>,
+ system_clause_type_variants: Vec<(&'static str, Arity, Variant)>,
+ compare_number_variants: Vec<(&'static str, Arity, Variant)>,
+ compare_term_variants: Vec<(&'static str, Arity, Variant)>,
+ repl_code_ptr_variants: Vec<(&'static str, Arity, Variant)>,
+}
+
+impl InstructionData {
+ fn new() -> Self {
+ Self {
+ instr_variants: vec![],
+ clause_type_variants: vec![],
+ builtin_type_variants: vec![],
+ inlined_type_variants: vec![],
+ system_clause_type_variants: vec![],
+ compare_number_variants: vec![],
+ compare_term_variants: vec![],
+ repl_code_ptr_variants: vec![],
+ }
+ }
+
+ fn label_variant(&mut self, id: &Ident, prefix: &'static str, variant: Variant) {
+ let (name, arity, countable_inference) = if id == "CompareNumber" {
+ let (name, arity) = add_discriminant_data::<CompareNumberDiscriminants>(
+ &variant,
+ prefix,
+ &mut self.compare_number_variants,
+ );
+
+ (name, arity, CountableInference::HasDefault)
+ } else if id == "CompareTerm" {
+ let (name, arity) = add_discriminant_data::<CompareTermDiscriminants>(
+ &variant,
+ prefix,
+ &mut self.compare_term_variants,
+ );
+
+ (name, arity, CountableInference::HasDefault)
+ } else if id == "BuiltInClauseType" {
+ let (name, arity) = add_discriminant_data::<BuiltInClauseTypeDiscriminants>(
+ &variant,
+ prefix,
+ &mut self.builtin_type_variants,
+ );
+
+ (name, arity, CountableInference::HasDefault)
+ } else if id == "InlinedClauseType" {
+ let (name, arity) = add_discriminant_data::<InlinedClauseTypeDiscriminants>(
+ &variant,
+ prefix,
+ &mut self.inlined_type_variants,
+ );
+
+ (name, arity, CountableInference::NotCounted)
+ } else if id == "REPLCodePtr" {
+ let (name, arity) = add_discriminant_data::<REPLCodePtrDiscriminants>(
+ &variant,
+ prefix,
+ &mut self.repl_code_ptr_variants,
+ );
+
+ (name, arity, CountableInference::NotCounted)
+ } else if id == "SystemClauseType" {
+ let (name, arity) = add_discriminant_data::<SystemClauseTypeDiscriminants>(
+ &variant,
+ prefix,
+ &mut self.system_clause_type_variants,
+ );
+
+ (name, arity, CountableInference::NotCounted)
+ } else if id == "InstructionTemplate" {
+ ( prop_from_ident::<InstructionTemplateDiscriminants>(&variant.ident, "Name"),
+ Arity::from(prop_from_ident::<InstructionTemplateDiscriminants>(&variant.ident, "Arity")),
+ CountableInference::NotCounted
+ )
+ } else if id == "ClauseType" {
+ let (name, arity) = add_discriminant_data::<ClauseTypeDiscriminants>(
+ &variant,
+ prefix,
+ &mut self.clause_type_variants,
+ );
+
+ (name, arity, CountableInference::HasDefault)
+ } else {
+ panic!("type ID is: {}", id);
+ };
+
+ let v_string = variant.ident.to_string();
+
+ let v_ident = if v_string.starts_with("Call") {
+ format_ident!("{}", v_string["Call".len() ..])
+ } else {
+ variant.ident.clone()
+ };
+
+ let generated_variant = create_instr_variant(
+ format_ident!("{}{}", prefix, v_ident),
+ variant.clone(),
+ );
+
+ self.instr_variants.push(
+ (name, arity, countable_inference, generated_variant)
+ );
+ }
+
+ fn generate_instruction_enum_loop(&mut self, input: syn::DeriveInput) {
+ if let Data::Enum(DataEnum { variants, .. }) = input.data {
+ for mut variant in variants {
+ if let Some(field) = variant.fields.iter().next() {
+ if let Some(input) = derive_input(&field.ty) {
+ self.generate_instruction_enum_loop(input);
+ continue;
+ }
+ }
+
+ if input.ident == "InstructionTemplate" {
+ variant.attrs.clear();
+ self.label_variant(&input.ident, "", variant);
+ continue;
+ }
+
+ self.label_variant(&input.ident, "Call", variant.clone());
+ self.label_variant(&input.ident, "Execute", variant.clone());
+
+ if input.ident == "BuiltInClauseType" ||
+ input.ident == "CompareNumber" ||
+ input.ident == "CompareTerm" ||
+ input.ident == "ClauseType"
+ {
+ self.label_variant(&input.ident, "DefaultCall", variant.clone());
+ self.label_variant(&input.ident, "DefaultExecute", variant);
+ }
+ }
+ } else {
+ panic!("{} must be an enum!", input.ident);
+ }
+ }
+}
+++ /dev/null
-[package]
-name = "prolog_parser"
-version = "0.8.68"
-edition = "2021"
-repository = "https://github.com/mthom/scryer-prolog"
-description = " An operator precedence parser for the Rebis development version of Scryer Prolog, an up and coming ISO Prolog implementation."
-license = "BSD-3-Clause"
-
-[dependencies]
-indexmap = "1.0.2"
-lexical = "5.2.1"
-ordered-float = "0.5.0"
-rug = { optional = true, version = "1.4.0" }
-num-rug-adapter = { optional = true, path = "../num-rug-adapter" }
-unicode_reader = "1.0.0"
-
-[lib]
-path = "src/lib.rs"
-
-[features]
-num = ["num-rug-adapter"]
-# no default features to make num tests work
-# workaround for --no-default-features and --features not working intuitively for workspaces with a root package
-# see rust-lang/cargo#7160
-# default = ["rug"]
[package]
name = "static-string-indexing"
version = "0.1.0"
-edition = "2018"
+edition = "2021"
[dependencies]
proc-macro2 = "*"
--- /dev/null
+[package]
+name = "to-syn-value"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[dependencies]
+syn = { version = "*", features = ['full', 'visit', 'extra-traits'] }
+to-syn-value_derive = { path = "../to-syn-value_derive" }
\ No newline at end of file
--- /dev/null
+pub trait ToDeriveInput {
+ fn to_derive_input() -> syn::DeriveInput;
+}
--- /dev/null
+[package]
+name = "to-syn-value_derive"
+version = "0.1.0"
+edition = "2021"
+publish = false
+
+[lib]
+proc-macro = true
+
+[dependencies]
+proc-macro2 = "*"
+syn = { version = "*", features = ['full', 'visit', 'extra-traits'] }
+quote = "*"
\ No newline at end of file
--- /dev/null
+use syn::*;
+use quote::*;
+
+#[proc_macro_derive(ToDeriveInput)]
+pub fn derive_to_derive_input(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ let derive_input = parse_macro_input!(input as DeriveInput);
+ let ty_name = derive_input.ident.clone();
+
+ quote! {
+ use to_syn_value::*;
+
+ impl ToDeriveInput for #ty_name {
+ fn to_derive_input() -> syn::DeriveInput {
+ syn::parse_quote! {
+ #derive_input
+ }
+ }
+ }
+ }.into()
+}
use crate::fixtures::*;
use crate::forms::*;
+use crate::instructions::*;
use crate::machine::machine_indices::*;
use std::cell::Cell;
pub(crate) trait Allocator<'a> {
fn new() -> Self;
- fn mark_anon_var<Target>(&mut self, _: Level, _: GenContext, _: &mut Vec<Target>)
+ fn mark_anon_var<Target>(&mut self, _: Level, _: GenContext, _: &mut Code)
where
Target: crate::targets::CompilationTarget<'a>;
fn mark_non_var<Target>(
_: Level,
_: GenContext,
_: &'a Cell<RegType>,
- _: &mut Vec<Target>,
+ _: &mut Code,
) where
Target: crate::targets::CompilationTarget<'a>;
fn mark_reserved_var<Target>(
_: Level,
_: &'a Cell<VarReg>,
_: GenContext,
- _: &mut Vec<Target>,
+ _: &mut Code,
_: RegType,
_: bool,
) where
_: Level,
_: &'a Cell<VarReg>,
_: GenContext,
- _: &mut Vec<Target>,
+ _: &mut Code,
) where
Target: crate::targets::CompilationTarget<'a>;
use crate::arena::*;
use crate::atom_table::*;
-use crate::clause_types::*;
use crate::fixtures::*;
use crate::forms::*;
use crate::instructions::*;
use std::rc::Rc;
use std::vec::Vec;
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum ArithmeticTerm {
+ Reg(RegType),
+ Interm(usize),
+ Number(Number),
+}
+
+impl ArithmeticTerm {
+ pub(crate) fn interm_or(&self, interm: usize) -> usize {
+ if let &ArithmeticTerm::Interm(interm) = self {
+ interm
+ } else {
+ interm
+ }
+ }
+}
+
+impl Default for ArithmeticTerm {
+ fn default() -> Self {
+ ArithmeticTerm::Number(Number::default())
+ }
+}
+
#[derive(Debug)]
pub(crate) struct ArithInstructionIterator<'a> {
state_stack: Vec<TermIterState<'a>>,
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms))
}
ClauseType::Inlined(InlinedClauseType::IsFloat(_)) => {
- let ct = ClauseType::Named(atom!("float"), 1, CodeIndex::default());
+ let ct = ClauseType::Named(1, atom!("float"), CodeIndex::default());
Ok(TermIterState::Clause(Level::Shallow, 0, cell, ct, terms))
}
_ => Err(ArithmeticError::NonEvaluableFunctor(
name: Atom,
a1: ArithmeticTerm,
t: usize,
- ) -> Result<ArithmeticInstruction, ArithmeticError> {
+ ) -> Result<Instruction, ArithmeticError> {
match name {
- atom!("abs") => Ok(ArithmeticInstruction::Abs(a1, t)),
- atom!("-") => Ok(ArithmeticInstruction::Neg(a1, t)),
- atom!("+") => Ok(ArithmeticInstruction::Plus(a1, t)),
- atom!("cos") => Ok(ArithmeticInstruction::Cos(a1, t)),
- atom!("sin") => Ok(ArithmeticInstruction::Sin(a1, t)),
- atom!("tan") => Ok(ArithmeticInstruction::Tan(a1, t)),
- atom!("log") => Ok(ArithmeticInstruction::Log(a1, t)),
- atom!("exp") => Ok(ArithmeticInstruction::Exp(a1, t)),
- atom!("sqrt") => Ok(ArithmeticInstruction::Sqrt(a1, t)),
- atom!("acos") => Ok(ArithmeticInstruction::ACos(a1, t)),
- atom!("asin") => Ok(ArithmeticInstruction::ASin(a1, t)),
- atom!("atan") => Ok(ArithmeticInstruction::ATan(a1, t)),
- atom!("float") => Ok(ArithmeticInstruction::Float(a1, t)),
- atom!("truncate") => Ok(ArithmeticInstruction::Truncate(a1, t)),
- atom!("round") => Ok(ArithmeticInstruction::Round(a1, t)),
- atom!("ceiling") => Ok(ArithmeticInstruction::Ceiling(a1, t)),
- atom!("floor") => Ok(ArithmeticInstruction::Floor(a1, t)),
- atom!("sign") => Ok(ArithmeticInstruction::Sign(a1, t)),
- atom!("\\") => Ok(ArithmeticInstruction::BitwiseComplement(a1, t)),
+ atom!("abs") => Ok(Instruction::Abs(a1, t)),
+ atom!("-") => Ok(Instruction::Neg(a1, t)),
+ atom!("+") => Ok(Instruction::Plus(a1, t)),
+ atom!("cos") => Ok(Instruction::Cos(a1, t)),
+ atom!("sin") => Ok(Instruction::Sin(a1, t)),
+ atom!("tan") => Ok(Instruction::Tan(a1, t)),
+ atom!("log") => Ok(Instruction::Log(a1, t)),
+ atom!("exp") => Ok(Instruction::Exp(a1, t)),
+ atom!("sqrt") => Ok(Instruction::Sqrt(a1, t)),
+ atom!("acos") => Ok(Instruction::ACos(a1, t)),
+ atom!("asin") => Ok(Instruction::ASin(a1, t)),
+ atom!("atan") => Ok(Instruction::ATan(a1, t)),
+ atom!("float") => Ok(Instruction::Float(a1, t)),
+ atom!("truncate") => Ok(Instruction::Truncate(a1, t)),
+ atom!("round") => Ok(Instruction::Round(a1, t)),
+ atom!("ceiling") => Ok(Instruction::Ceiling(a1, t)),
+ atom!("floor") => Ok(Instruction::Floor(a1, t)),
+ atom!("sign") => Ok(Instruction::Sign(a1, t)),
+ atom!("\\") => Ok(Instruction::BitwiseComplement(a1, t)),
_ => Err(ArithmeticError::NonEvaluableFunctor(Literal::Atom(name), 1)),
}
}
a1: ArithmeticTerm,
a2: ArithmeticTerm,
t: usize,
- ) -> Result<ArithmeticInstruction, ArithmeticError> {
+ ) -> Result<Instruction, ArithmeticError> {
match name {
- atom!("+") => Ok(ArithmeticInstruction::Add(a1, a2, t)),
- atom!("-") => Ok(ArithmeticInstruction::Sub(a1, a2, t)),
- atom!("/") => Ok(ArithmeticInstruction::Div(a1, a2, t)),
- atom!("//") => Ok(ArithmeticInstruction::IDiv(a1, a2, t)),
- atom!("max") => Ok(ArithmeticInstruction::Max(a1, a2, t)),
- atom!("min") => Ok(ArithmeticInstruction::Min(a1, a2, t)),
- atom!("div") => Ok(ArithmeticInstruction::IntFloorDiv(a1, a2, t)),
- atom!("rdiv") => Ok(ArithmeticInstruction::RDiv(a1, a2, t)),
- atom!("*") => Ok(ArithmeticInstruction::Mul(a1, a2, t)),
- atom!("**") => Ok(ArithmeticInstruction::Pow(a1, a2, t)),
- atom!("^") => Ok(ArithmeticInstruction::IntPow(a1, a2, t)),
- atom!(">>") => Ok(ArithmeticInstruction::Shr(a1, a2, t)),
- atom!("<<") => Ok(ArithmeticInstruction::Shl(a1, a2, t)),
- atom!("/\\") => Ok(ArithmeticInstruction::And(a1, a2, t)),
- atom!("\\/") => Ok(ArithmeticInstruction::Or(a1, a2, t)),
- atom!("xor") => Ok(ArithmeticInstruction::Xor(a1, a2, t)),
- atom!("mod") => Ok(ArithmeticInstruction::Mod(a1, a2, t)),
- atom!("rem") => Ok(ArithmeticInstruction::Rem(a1, a2, t)),
- atom!("gcd") => Ok(ArithmeticInstruction::Gcd(a1, a2, t)),
- atom!("atan2") => Ok(ArithmeticInstruction::ATan2(a1, a2, t)),
+ atom!("+") => Ok(Instruction::Add(a1, a2, t)),
+ atom!("-") => Ok(Instruction::Sub(a1, a2, t)),
+ atom!("/") => Ok(Instruction::Div(a1, a2, t)),
+ atom!("//") => Ok(Instruction::IDiv(a1, a2, t)),
+ atom!("max") => Ok(Instruction::Max(a1, a2, t)),
+ atom!("min") => Ok(Instruction::Min(a1, a2, t)),
+ atom!("div") => Ok(Instruction::IntFloorDiv(a1, a2, t)),
+ atom!("rdiv") => Ok(Instruction::RDiv(a1, a2, t)),
+ atom!("*") => Ok(Instruction::Mul(a1, a2, t)),
+ atom!("**") => Ok(Instruction::Pow(a1, a2, t)),
+ atom!("^") => Ok(Instruction::IntPow(a1, a2, t)),
+ atom!(">>") => Ok(Instruction::Shr(a1, a2, t)),
+ atom!("<<") => Ok(Instruction::Shl(a1, a2, t)),
+ atom!("/\\") => Ok(Instruction::And(a1, a2, t)),
+ atom!("\\/") => Ok(Instruction::Or(a1, a2, t)),
+ atom!("xor") => Ok(Instruction::Xor(a1, a2, t)),
+ atom!("mod") => Ok(Instruction::Mod(a1, a2, t)),
+ atom!("rem") => Ok(Instruction::Rem(a1, a2, t)),
+ atom!("gcd") => Ok(Instruction::Gcd(a1, a2, t)),
+ atom!("atan2") => Ok(Instruction::ATan2(a1, a2, t)),
_ => Err(ArithmeticError::NonEvaluableFunctor(Literal::Atom(name), 2)),
}
}
&mut self,
name: Atom,
arity: usize,
- ) -> Result<ArithmeticInstruction, ArithmeticError> {
+ ) -> Result<Instruction, ArithmeticError> {
match arity {
1 => {
let a1 = self.interm.pop().unwrap();
self.interm.push(ArithmeticTerm::Reg(r));
}
ArithTermRef::Op(name, arity) => {
- code.push(Line::Arithmetic(self.instr_from_clause(name, arity)?));
+ code.push(self.instr_from_clause(name, arity)?);
}
}
}
+++ /dev/null
-use crate::atom_table::*;
-use crate::machine::machine_indices::*;
-use crate::parser::ast::*;
-use crate::parser::rug::rand::RandState;
-
-use crate::forms::Number;
-use crate::temp_v;
-
-use ref_thread_local::{ref_thread_local};
-
-#[derive(Debug, Clone, Copy, Eq, PartialEq)]
-pub enum CompareNumberQT {
- GreaterThan,
- LessThan,
- GreaterThanOrEqual,
- LessThanOrEqual,
- NotEqual,
- Equal,
-}
-
-impl CompareNumberQT {
- fn name(self) -> Atom {
- match self {
- CompareNumberQT::GreaterThan => atom!(">"),
- CompareNumberQT::LessThan => atom!("<"),
- CompareNumberQT::GreaterThanOrEqual => atom!(">="),
- CompareNumberQT::LessThanOrEqual => atom!("=<"),
- CompareNumberQT::NotEqual => atom!("=\\="),
- CompareNumberQT::Equal => atom!("=:="),
- }
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum CompareTermQT {
- LessThan,
- LessThanOrEqual,
- GreaterThanOrEqual,
- GreaterThan,
-}
-
-impl CompareTermQT {
- fn name(self) -> Atom {
- match self {
- CompareTermQT::GreaterThan => atom!("@>"),
- CompareTermQT::LessThan => atom!("@<"),
- CompareTermQT::GreaterThanOrEqual => atom!("@>="),
- CompareTermQT::LessThanOrEqual => atom!("@=<"),
- }
- }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum ArithmeticTerm {
- Reg(RegType),
- Interm(usize),
- Number(Number),
-}
-
-impl ArithmeticTerm {
- pub(crate) fn interm_or(&self, interm: usize) -> usize {
- if let &ArithmeticTerm::Interm(interm) = self {
- interm
- } else {
- interm
- }
- }
-}
-
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub enum InlinedClauseType {
- CompareNumber(CompareNumberQT, ArithmeticTerm, ArithmeticTerm),
- IsAtom(RegType),
- IsAtomic(RegType),
- IsCompound(RegType),
- IsInteger(RegType),
- IsNumber(RegType),
- IsRational(RegType),
- IsFloat(RegType),
- IsNonVar(RegType),
- IsVar(RegType),
-}
-
-ref_thread_local! {
- pub(crate) static managed RANDOM_STATE: RandState<'static> = RandState::new();
-}
-
-pub fn clause_type_form(name: Atom, arity: usize) -> Option<ClauseType> {
- match (name, arity) {
- (atom!(">"), 2) => Some(ClauseType::Inlined(InlinedClauseType::CompareNumber(
- CompareNumberQT::GreaterThan,
- ar_reg!(temp_v!(1)),
- ar_reg!(temp_v!(2)),
- ))),
- (atom!("<"), 2) => Some(ClauseType::Inlined(InlinedClauseType::CompareNumber(
- CompareNumberQT::LessThan,
- ar_reg!(temp_v!(1)),
- ar_reg!(temp_v!(2)),
- ))),
- (atom!(">="), 2) => Some(ClauseType::Inlined(InlinedClauseType::CompareNumber(
- CompareNumberQT::GreaterThanOrEqual,
- ar_reg!(temp_v!(1)),
- ar_reg!(temp_v!(2)),
- ))),
- (atom!("=<"), 2) => Some(ClauseType::Inlined(InlinedClauseType::CompareNumber(
- CompareNumberQT::LessThanOrEqual,
- ar_reg!(temp_v!(1)),
- ar_reg!(temp_v!(2)),
- ))),
- (atom!("=:="), 2) => Some(ClauseType::Inlined(InlinedClauseType::CompareNumber(
- CompareNumberQT::Equal,
- ar_reg!(temp_v!(1)),
- ar_reg!(temp_v!(2)),
- ))),
- (atom!("=\\="), 2) => Some(ClauseType::Inlined(InlinedClauseType::CompareNumber(
- CompareNumberQT::NotEqual,
- ar_reg!(temp_v!(1)),
- ar_reg!(temp_v!(2)),
- ))),
- (atom!("atom"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsAtom(temp_v!(1)))),
- (atom!("atomic"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsAtomic(temp_v!(1)))),
- (atom!("compound"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsCompound(temp_v!(
- 1
- )))),
- (atom!("integer"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsInteger(temp_v!(
- 1
- )))),
- (atom!("number"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsNumber(temp_v!(1)))),
- (atom!("rational"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsRational(temp_v!(
- 1
- )))),
- (atom!("float"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsFloat(temp_v!(1)))),
- (atom!("nonvar"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsNonVar(temp_v!(1)))),
- (atom!("var"), 1) => Some(ClauseType::Inlined(InlinedClauseType::IsVar(temp_v!(1)))),
- (atom!("acyclic_term"), 1) => Some(ClauseType::BuiltIn(BuiltInClauseType::AcyclicTerm)),
- (atom!("arg"), 3) => Some(ClauseType::BuiltIn(BuiltInClauseType::Arg)),
- (atom!("compare"), 3) => Some(ClauseType::BuiltIn(BuiltInClauseType::Compare)),
- (atom!("@>"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(
- CompareTermQT::GreaterThan,
- ))),
- (atom!("@<"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(
- CompareTermQT::LessThan,
- ))),
- (atom!("@>="), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(
- CompareTermQT::GreaterThanOrEqual,
- ))),
- (atom!("@=<"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::CompareTerm(
- CompareTermQT::LessThanOrEqual,
- ))),
- (atom!("copy_term"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::CopyTerm)),
- (atom!("=="), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::Eq)),
- (atom!("functor"), 3) => Some(ClauseType::BuiltIn(BuiltInClauseType::Functor)),
- (atom!("ground"), 1) => Some(ClauseType::BuiltIn(BuiltInClauseType::Ground)),
- (atom!("is"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::Is(
- temp_v!(1),
- ar_reg!(temp_v!(2)),
- ))),
- (atom!("keysort"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::KeySort)),
- (atom!("\\=="), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::NotEq)),
- (atom!("read"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::Read)),
- (atom!("sort"), 2) => Some(ClauseType::BuiltIn(BuiltInClauseType::Sort)),
- _ => None,
- }
-}
-
-impl InlinedClauseType {
- pub(crate) fn name(&self) -> Atom {
- match self {
- &InlinedClauseType::CompareNumber(qt, ..) => qt.name(),
- &InlinedClauseType::IsAtom(..) => atom!("atom"),
- &InlinedClauseType::IsAtomic(..) => atom!("atomic"),
- &InlinedClauseType::IsCompound(..) => atom!("compound"),
- &InlinedClauseType::IsNumber(..) => atom!("number"),
- &InlinedClauseType::IsInteger(..) => atom!("integer"),
- &InlinedClauseType::IsRational(..) => atom!("rational"),
- &InlinedClauseType::IsFloat(..) => atom!("float"),
- &InlinedClauseType::IsNonVar(..) => atom!("nonvar"),
- &InlinedClauseType::IsVar(..) => atom!("var"),
- }
- }
-}
-
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub enum SystemClauseType {
- AtomChars,
- AtomCodes,
- AtomLength,
- BindFromRegister,
- CallContinuation,
- CharCode,
- CharType,
- CharsToNumber,
- CodesToNumber,
- CopyTermWithoutAttrVars,
- CheckCutPoint,
- Close,
- CopyToLiftedHeap,
- CreatePartialString,
- CurrentHostname,
- CurrentInput,
- CurrentOutput,
- DirectoryFiles,
- FileSize,
- FileExists,
- DirectoryExists,
- DirectorySeparator,
- MakeDirectory,
- MakeDirectoryPath,
- DeleteFile,
- RenameFile,
- WorkingDirectory,
- DeleteDirectory,
- PathCanonical,
- FileTime,
- DeleteAttribute,
- DeleteHeadAttribute,
- DynamicModuleResolution(usize),
- EnqueueAttributedVar,
- FetchGlobalVar,
- FirstStream,
- FlushOutput,
- GetByte,
- GetChar,
- GetNChars,
- GetCode,
- GetSingleChar,
- ResetAttrVarState,
- TruncateIfNoLiftedHeapGrowthDiff,
- TruncateIfNoLiftedHeapGrowth,
- GetAttributedVariableList,
- GetAttrVarQueueDelimiter,
- GetAttrVarQueueBeyond,
- GetBValue,
- GetContinuationChunk,
- GetNextDBRef,
- GetNextOpDBRef,
- IsPartialString,
- Halt,
- GetLiftedHeapFromOffset,
- GetLiftedHeapFromOffsetDiff,
- GetSCCCleaner,
- HeadIsDynamic,
- InstallSCCCleaner,
- InstallInferenceCounter,
- LiftedHeapLength,
- LoadLibraryAsStream,
- ModuleExists,
- NextEP,
- NoSuchPredicate,
- NumberToChars,
- NumberToCodes,
- OpDeclaration,
- Open,
- SetStreamOptions,
- NextStream,
- PartialStringTail,
- PeekByte,
- PeekChar,
- PeekCode,
- PointsToContinuationResetMarker,
- PutByte,
- PutChar,
- PutChars,
- PutCode,
- REPL(REPLCodePtr),
- ReadQueryTerm,
- ReadTerm,
- RedoAttrVarBinding,
- RemoveCallPolicyCheck,
- RemoveInferenceCounter,
- ResetContinuationMarker,
- RestoreCutPolicy,
- SetCutPoint(RegType),
- SetInput,
- SetOutput,
- StoreBacktrackableGlobalVar,
- StoreGlobalVar,
- StreamProperty,
- SetStreamPosition,
- InferenceLevel,
- CleanUpBlock,
- EraseBall,
- Fail,
- GetBall,
- GetCurrentBlock,
- GetCutPoint,
- GetStaggeredCutPoint,
- GetDoubleQuotes,
- InstallNewBlock,
- Maybe,
- CpuNow,
- CurrentTime,
- QuotedToken,
- ReadTermFromChars,
- ResetBlock,
- ReturnFromVerifyAttr,
- SetBall,
- SetCutPointByDefault(RegType),
- SetDoubleQuotes,
- SetSeed,
- SkipMaxList,
- Sleep,
- SocketClientOpen,
- SocketServerOpen,
- SocketServerAccept,
- SocketServerClose,
- TLSAcceptClient,
- TLSClientConnect,
- Succeed,
- TermAttributedVariables,
- TermVariables,
- TermVariablesUnderMaxDepth,
- TruncateLiftedHeapTo,
- UnifyWithOccursCheck,
- UnwindEnvironments,
- UnwindStack,
- WAMInstructions,
- WriteTerm,
- WriteTermToChars,
- ScryerPrologVersion,
- CryptoRandomByte,
- CryptoDataHash,
- CryptoDataHKDF,
- CryptoPasswordHash,
- CryptoDataEncrypt,
- CryptoDataDecrypt,
- CryptoCurveScalarMult,
- Ed25519Sign,
- Ed25519Verify,
- Ed25519NewKeyPair,
- Ed25519KeyPairPublicKey,
- Curve25519ScalarMult,
- FirstNonOctet,
- LoadHTML,
- LoadXML,
- GetEnv,
- SetEnv,
- UnsetEnv,
- Shell,
- PID,
- CharsBase64,
- DevourWhitespace,
- IsSTOEnabled,
- SetSTOAsUnify,
- SetNSTOAsUnify,
- SetSTOWithErrorAsUnify,
- HomeDirectory,
- DebugHook,
- PopCount
-}
-
-impl SystemClauseType {
- pub(crate) fn name(&self) -> Atom {
- match self {
- &SystemClauseType::AtomChars => atom!("$atom_chars"),
- &SystemClauseType::AtomCodes => atom!("$atom_codes"),
- &SystemClauseType::AtomLength => atom!("$atom_length"),
- &SystemClauseType::BindFromRegister => atom!("$bind_from_register"),
- &SystemClauseType::CallContinuation => atom!("$call_continuation"),
- &SystemClauseType::CharCode => atom!("$char_code"),
- &SystemClauseType::CharType => atom!("$char_type"),
- &SystemClauseType::CharsToNumber => atom!("$chars_to_number"),
- &SystemClauseType::CheckCutPoint => atom!("$check_cp"),
- &SystemClauseType::CodesToNumber => atom!("$codes_to_number"),
- &SystemClauseType::CopyTermWithoutAttrVars => {
- atom!("$copy_term_without_attr_vars")
- }
- &SystemClauseType::CreatePartialString => atom!("$create_partial_string"),
- &SystemClauseType::CurrentInput => atom!("$current_input"),
- &SystemClauseType::CurrentHostname => atom!("$current_hostname"),
- &SystemClauseType::CurrentOutput => atom!("$current_output"),
- &SystemClauseType::DirectoryFiles => atom!("$directory_files"),
- &SystemClauseType::FileSize => atom!("$file_size"),
- &SystemClauseType::FileExists => atom!("$file_exists"),
- &SystemClauseType::DirectoryExists => atom!("$directory_exists"),
- &SystemClauseType::DirectorySeparator => atom!("$directory_separator"),
- &SystemClauseType::MakeDirectory => atom!("$make_directory"),
- &SystemClauseType::MakeDirectoryPath => atom!("$make_directory_path"),
- &SystemClauseType::DeleteFile => atom!("$delete_file"),
- &SystemClauseType::RenameFile => atom!("$rename_file"),
- &SystemClauseType::DeleteDirectory => atom!("$delete_directory"),
- &SystemClauseType::WorkingDirectory => atom!("$working_directory"),
- &SystemClauseType::PathCanonical => atom!("$path_canonical"),
- &SystemClauseType::FileTime => atom!("$file_time"),
- &SystemClauseType::REPL(REPLCodePtr::AddDiscontiguousPredicate) => {
- atom!("$add_discontiguous_predicate")
- }
- &SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate) => atom!("$add_dynamic_predicate"),
- &SystemClauseType::REPL(REPLCodePtr::AddMultifilePredicate) => {
- atom!("$add_multifile_predicate")
- }
- &SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause) => {
- atom!("$add_goal_expansion_clause")
- }
- &SystemClauseType::REPL(REPLCodePtr::AddTermExpansionClause) => {
- atom!("$add_term_expansion_clause")
- }
- &SystemClauseType::REPL(REPLCodePtr::ClauseToEvacuable) => atom!("$clause_to_evacuable"),
- &SystemClauseType::REPL(REPLCodePtr::ScopedClauseToEvacuable) => {
- atom!("$scoped_clause_to_evacuable")
- }
- &SystemClauseType::REPL(REPLCodePtr::ConcludeLoad) => atom!("$conclude_load"),
- &SystemClauseType::REPL(REPLCodePtr::DeclareModule) => atom!("$declare_module"),
- &SystemClauseType::REPL(REPLCodePtr::LoadCompiledLibrary) => atom!("$load_compiled_library"),
- &SystemClauseType::REPL(REPLCodePtr::PushLoadStatePayload) => {
- atom!("$push_load_state_payload")
- }
- &SystemClauseType::REPL(REPLCodePtr::AddInSituFilenameModule) => {
- atom!("$add_in_situ_filename_module")
- }
- &SystemClauseType::REPL(REPLCodePtr::Asserta) => atom!("$asserta"),
- &SystemClauseType::REPL(REPLCodePtr::Assertz) => atom!("$assertz"),
- &SystemClauseType::REPL(REPLCodePtr::Retract) => atom!("$retract_clause"),
- &SystemClauseType::REPL(REPLCodePtr::UseModule) => atom!("$use_module"),
- &SystemClauseType::REPL(REPLCodePtr::PushLoadContext) => atom!("$push_load_context"),
- &SystemClauseType::REPL(REPLCodePtr::PopLoadContext) => atom!("$pop_load_context"),
- &SystemClauseType::REPL(REPLCodePtr::PopLoadStatePayload) => atom!("$pop_load_state_payload"),
- &SystemClauseType::REPL(REPLCodePtr::LoadContextSource) => atom!("$prolog_lc_source"),
- &SystemClauseType::REPL(REPLCodePtr::LoadContextFile) => atom!("$prolog_lc_file"),
- &SystemClauseType::REPL(REPLCodePtr::LoadContextDirectory) => atom!("$prolog_lc_dir"),
- &SystemClauseType::REPL(REPLCodePtr::LoadContextModule) => atom!("$prolog_lc_module"),
- &SystemClauseType::REPL(REPLCodePtr::LoadContextStream) => atom!("$prolog_lc_stream"),
- &SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty) => {
- atom!("$cpp_meta_predicate_property")
- }
- &SystemClauseType::REPL(REPLCodePtr::BuiltInProperty) => atom!("$cpp_built_in_property"),
- &SystemClauseType::REPL(REPLCodePtr::DynamicProperty) => atom!("$cpp_dynamic_property"),
- &SystemClauseType::REPL(REPLCodePtr::MultifileProperty) => atom!("$cpp_multifile_property"),
- &SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty) => {
- atom!("$cpp_discontiguous_property")
- }
- &SystemClauseType::REPL(REPLCodePtr::AbolishClause) => atom!("$abolish_clause"),
- &SystemClauseType::REPL(REPLCodePtr::IsConsistentWithTermQueue) => {
- atom!("$is_consistent_with_term_queue")
- }
- &SystemClauseType::REPL(REPLCodePtr::FlushTermQueue) => atom!("$flush_term_queue"),
- &SystemClauseType::REPL(REPLCodePtr::RemoveModuleExports) => atom!("$remove_module_exports"),
- &SystemClauseType::REPL(REPLCodePtr::AddNonCountedBacktracking) => {
- atom!("$add_non_counted_backtracking")
- }
- &SystemClauseType::Close => atom!("$close"),
- &SystemClauseType::CopyToLiftedHeap => atom!("$copy_to_lh"),
- &SystemClauseType::DeleteAttribute => atom!("$del_attr_non_head"),
- &SystemClauseType::DeleteHeadAttribute => atom!("$del_attr_head"),
- &SystemClauseType::DynamicModuleResolution(_) => atom!("$module_call"),
- &SystemClauseType::EnqueueAttributedVar => atom!("$enqueue_attr_var"),
- &SystemClauseType::FetchGlobalVar => atom!("$fetch_global_var"),
- &SystemClauseType::FirstStream => atom!("$first_stream"),
- &SystemClauseType::FlushOutput => atom!("$flush_output"),
- &SystemClauseType::GetByte => atom!("$get_byte"),
- &SystemClauseType::GetChar => atom!("$get_char"),
- &SystemClauseType::GetNChars => atom!("$get_n_chars"),
- &SystemClauseType::GetCode => atom!("$get_code"),
- &SystemClauseType::GetSingleChar => atom!("$get_single_char"),
- &SystemClauseType::ResetAttrVarState => atom!("$reset_attr_var_state"),
- &SystemClauseType::TruncateIfNoLiftedHeapGrowth => atom!("$truncate_if_no_lh_growth"),
- &SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff => atom!("$truncate_if_no_lh_growth_diff"),
- &SystemClauseType::GetAttributedVariableList => atom!("$get_attr_list"),
- &SystemClauseType::GetAttrVarQueueDelimiter => atom!("$get_attr_var_queue_delim"),
- &SystemClauseType::GetAttrVarQueueBeyond => atom!("$get_attr_var_queue_beyond"),
- &SystemClauseType::GetContinuationChunk => atom!("$get_cont_chunk"),
- &SystemClauseType::GetLiftedHeapFromOffset => atom!("$get_lh_from_offset"),
- &SystemClauseType::GetLiftedHeapFromOffsetDiff => atom!("$get_lh_from_offset_diff"),
- &SystemClauseType::GetBValue => atom!("$get_b_value"),
- &SystemClauseType::GetNextDBRef => atom!("$get_next_db_ref"),
- &SystemClauseType::GetNextOpDBRef => atom!("$get_next_op_db_ref"),
- &SystemClauseType::GetDoubleQuotes => atom!("$get_double_quotes"),
- &SystemClauseType::GetSCCCleaner => atom!("$get_scc_cleaner"),
- &SystemClauseType::Halt => atom!("$halt"),
- &SystemClauseType::HeadIsDynamic => atom!("$head_is_dynamic"),
- &SystemClauseType::Open => atom!("$open"),
- &SystemClauseType::OpDeclaration => atom!("$op"),
- &SystemClauseType::InstallSCCCleaner => atom!("$install_scc_cleaner"),
- &SystemClauseType::InstallInferenceCounter => atom!("$install_inference_counter"),
- &SystemClauseType::IsPartialString => atom!("$is_partial_string"),
- &SystemClauseType::PartialStringTail => atom!("$partial_string_tail"),
- &SystemClauseType::PeekByte => atom!("$peek_byte"),
- &SystemClauseType::PeekChar => atom!("$peek_char"),
- &SystemClauseType::PeekCode => atom!("$peek_code"),
- &SystemClauseType::LiftedHeapLength => atom!("$lh_length"),
- &SystemClauseType::Maybe => atom!("maybe"),
- &SystemClauseType::CpuNow => atom!("$cpu_now"),
- &SystemClauseType::CurrentTime => atom!("$current_time"),
- &SystemClauseType::ModuleExists => atom!("$module_exists"),
- &SystemClauseType::NextStream => atom!("$next_stream"),
- &SystemClauseType::NoSuchPredicate => atom!("$no_such_predicate"),
- &SystemClauseType::NumberToChars => atom!("$number_to_chars"),
- &SystemClauseType::NumberToCodes => atom!("$number_to_codes"),
- &SystemClauseType::PointsToContinuationResetMarker => {
- atom!("$points_to_cont_reset_marker")
- }
- &SystemClauseType::PutByte => {
- atom!("$put_byte")
- }
- &SystemClauseType::PutChar => {
- atom!("$put_char")
- }
- &SystemClauseType::PutChars => {
- atom!("$put_chars")
- }
- &SystemClauseType::PutCode => {
- atom!("$put_code")
- }
- &SystemClauseType::QuotedToken => {
- atom!("$quoted_token")
- }
- &SystemClauseType::RedoAttrVarBinding => atom!("$redo_attr_var_binding"),
- &SystemClauseType::RemoveCallPolicyCheck => atom!("$remove_call_policy_check"),
- &SystemClauseType::RemoveInferenceCounter => atom!("$remove_inference_counter"),
- &SystemClauseType::RestoreCutPolicy => atom!("$restore_cut_policy"),
- &SystemClauseType::SetCutPoint(_) => atom!("$set_cp"),
- &SystemClauseType::SetInput => atom!("$set_input"),
- &SystemClauseType::SetOutput => atom!("$set_output"),
- &SystemClauseType::SetSeed => atom!("$set_seed"),
- &SystemClauseType::StreamProperty => atom!("$stream_property"),
- &SystemClauseType::SetStreamPosition => atom!("$set_stream_position"),
- &SystemClauseType::SetStreamOptions => atom!("$set_stream_options"),
- &SystemClauseType::StoreBacktrackableGlobalVar => {
- atom!("$store_back_trackable_global_var")
- }
- &SystemClauseType::StoreGlobalVar => atom!("$store_global_var"),
- &SystemClauseType::InferenceLevel => atom!("$inference_level"),
- &SystemClauseType::CleanUpBlock => atom!("$clean_up_block"),
- &SystemClauseType::EraseBall => atom!("$erase_ball"),
- &SystemClauseType::Fail => atom!("$fail"),
- &SystemClauseType::GetBall => atom!("$get_ball"),
- &SystemClauseType::GetCutPoint => atom!("$get_cp"),
- &SystemClauseType::GetStaggeredCutPoint => atom!("$get_staggered_cp"),
- &SystemClauseType::GetCurrentBlock => atom!("$get_current_block"),
- &SystemClauseType::InstallNewBlock => atom!("$install_new_block"),
- &SystemClauseType::NextEP => atom!("$nextEP"),
- &SystemClauseType::ReadQueryTerm => atom!("$read_query_term"),
- &SystemClauseType::ReadTerm => atom!("$read_term"),
- &SystemClauseType::ReadTermFromChars => atom!("$read_term_from_chars"),
- &SystemClauseType::ResetBlock => atom!("$reset_block"),
- &SystemClauseType::ResetContinuationMarker => atom!("$reset_cont_marker"),
- &SystemClauseType::ReturnFromVerifyAttr => atom!("$return_from_verify_attr"),
- &SystemClauseType::SetBall => atom!("$set_ball"),
- &SystemClauseType::SetCutPointByDefault(_) => atom!("$set_cp_by_default"),
- &SystemClauseType::SetDoubleQuotes => atom!("$set_double_quotes"),
- &SystemClauseType::SkipMaxList => atom!("$skip_max_list"),
- &SystemClauseType::Sleep => atom!("$sleep"),
- &SystemClauseType::SocketClientOpen => atom!("$socket_client_open"),
- &SystemClauseType::SocketServerOpen => atom!("$socket_server_open"),
- &SystemClauseType::SocketServerAccept => atom!("$socket_server_accept"),
- &SystemClauseType::SocketServerClose => atom!("$socket_server_close"),
- &SystemClauseType::TLSAcceptClient => atom!("$tls_accept_client"),
- &SystemClauseType::TLSClientConnect => atom!("$tls_client_connect"),
- &SystemClauseType::Succeed => atom!("$succeed"),
- &SystemClauseType::TermAttributedVariables => {
- atom!("$term_attributed_variables")
- }
- &SystemClauseType::TermVariables => atom!("$term_variables"),
- &SystemClauseType::TermVariablesUnderMaxDepth => atom!("$term_variables_under_max_depth"),
- &SystemClauseType::TruncateLiftedHeapTo => atom!("$truncate_lh_to"),
- &SystemClauseType::UnifyWithOccursCheck => atom!("$unify_with_occurs_check"),
- &SystemClauseType::UnwindEnvironments => atom!("$unwind_environments"),
- &SystemClauseType::UnwindStack => atom!("$unwind_stack"),
- &SystemClauseType::WAMInstructions => atom!("$wam_instructions"),
- &SystemClauseType::WriteTerm => atom!("$write_term"),
- &SystemClauseType::WriteTermToChars => atom!("$write_term_to_chars"),
- &SystemClauseType::ScryerPrologVersion => atom!("$scryer_prolog_version"),
- &SystemClauseType::CryptoRandomByte => atom!("$crypto_random_byte"),
- &SystemClauseType::CryptoDataHash => atom!("$crypto_data_hash"),
- &SystemClauseType::CryptoDataHKDF => atom!("$crypto_data_hkdf"),
- &SystemClauseType::CryptoPasswordHash => atom!("$crypto_password_hash"),
- &SystemClauseType::CryptoDataEncrypt => atom!("$crypto_data_encrypt"),
- &SystemClauseType::CryptoDataDecrypt => atom!("$crypto_data_decrypt"),
- &SystemClauseType::CryptoCurveScalarMult => atom!("$crypto_curve_scalar_mult"),
- &SystemClauseType::Ed25519Sign => atom!("$ed25519_sign"),
- &SystemClauseType::Ed25519Verify => atom!("$ed25519_verify"),
- &SystemClauseType::Ed25519NewKeyPair => atom!("$ed25519_new_keypair"),
- &SystemClauseType::Ed25519KeyPairPublicKey => {
- atom!("$ed25519_keypair_public_key")
- }
- &SystemClauseType::Curve25519ScalarMult => atom!("$curve25519_scalar_mult"),
- &SystemClauseType::FirstNonOctet => atom!("$first_non_octet"),
- &SystemClauseType::LoadHTML => atom!("$load_html"),
- &SystemClauseType::LoadXML => atom!("$load_xml"),
- &SystemClauseType::GetEnv => atom!("$getenv"),
- &SystemClauseType::SetEnv => atom!("$setenv"),
- &SystemClauseType::UnsetEnv => atom!("$unsetenv"),
- &SystemClauseType::Shell => atom!("$shell"),
- &SystemClauseType::PID => atom!("$pid"),
- &SystemClauseType::CharsBase64 => atom!("$chars_base64"),
- &SystemClauseType::LoadLibraryAsStream => atom!("$load_library_as_stream"),
- &SystemClauseType::DevourWhitespace => atom!("$devour_whitespace"),
- &SystemClauseType::IsSTOEnabled => atom!("$is_sto_enabled"),
- &SystemClauseType::SetSTOAsUnify => atom!("$set_sto_as_unify"),
- &SystemClauseType::SetNSTOAsUnify => atom!("$set_nsto_as_unify"),
- &SystemClauseType::HomeDirectory => atom!("$home_directory"),
- &SystemClauseType::SetSTOWithErrorAsUnify => {
- atom!("$set_sto_with_error_as_unify")
- }
- &SystemClauseType::DebugHook => atom!("$debug_hook"),
- &SystemClauseType::PopCount => atom!("$popcount"),
- }
- }
-
- pub(crate) fn from(name: Atom, arity: usize) -> Option<SystemClauseType> {
- match (name, arity) {
- (atom!("$abolish_clause"), 3) => Some(SystemClauseType::REPL(REPLCodePtr::AbolishClause)),
- (atom!("$add_dynamic_predicate"), 4) => {
- Some(SystemClauseType::REPL(REPLCodePtr::AddDynamicPredicate))
- }
- (atom!("$add_multifile_predicate"), 4) => {
- Some(SystemClauseType::REPL(REPLCodePtr::AddMultifilePredicate))
- }
- (atom!("$add_discontiguous_predicate"), 4) => Some(SystemClauseType::REPL(
- REPLCodePtr::AddDiscontiguousPredicate,
- )),
- (atom!("$add_goal_expansion_clause"), 3) => {
- Some(SystemClauseType::REPL(REPLCodePtr::AddGoalExpansionClause))
- }
- (atom!("$add_term_expansion_clause"), 2) => {
- Some(SystemClauseType::REPL(REPLCodePtr::AddTermExpansionClause))
- }
- (atom!("$atom_chars"), 2) => Some(SystemClauseType::AtomChars),
- (atom!("$atom_codes"), 2) => Some(SystemClauseType::AtomCodes),
- (atom!("$atom_length"), 2) => Some(SystemClauseType::AtomLength),
- (atom!("$bind_from_register"), 2) => Some(SystemClauseType::BindFromRegister),
- (atom!("$call_continuation"), 1) => Some(SystemClauseType::CallContinuation),
- (atom!("$char_code"), 2) => Some(SystemClauseType::CharCode),
- (atom!("$char_type"), 2) => Some(SystemClauseType::CharType),
- (atom!("$chars_to_number"), 2) => Some(SystemClauseType::CharsToNumber),
- (atom!("$codes_to_number"), 2) => Some(SystemClauseType::CodesToNumber),
- (atom!("$copy_term_without_attr_vars"), 2) => Some(SystemClauseType::CopyTermWithoutAttrVars),
- (atom!("$create_partial_string"), 3) => Some(SystemClauseType::CreatePartialString),
- (atom!("$check_cp"), 1) => Some(SystemClauseType::CheckCutPoint),
- (atom!("$copy_to_lh"), 2) => Some(SystemClauseType::CopyToLiftedHeap),
- (atom!("$close"), 2) => Some(SystemClauseType::Close),
- (atom!("$current_hostname"), 1) => Some(SystemClauseType::CurrentHostname),
- (atom!("$current_input"), 1) => Some(SystemClauseType::CurrentInput),
- (atom!("$current_output"), 1) => Some(SystemClauseType::CurrentOutput),
- (atom!("$first_stream"), 1) => Some(SystemClauseType::FirstStream),
- (atom!("$next_stream"), 2) => Some(SystemClauseType::NextStream),
- (atom!("$flush_output"), 1) => Some(SystemClauseType::FlushOutput),
- (atom!("$del_attr_non_head"), 1) => Some(SystemClauseType::DeleteAttribute),
- (atom!("$del_attr_head"), 1) => Some(SystemClauseType::DeleteHeadAttribute),
- (atom!("$get_next_db_ref"), 4) => Some(SystemClauseType::GetNextDBRef),
- (atom!("$get_next_op_db_ref"), 7) => Some(SystemClauseType::GetNextOpDBRef),
- (atom!("$module_call"), _) => Some(SystemClauseType::DynamicModuleResolution(arity - 2)),
- (atom!("$enqueue_attr_var"), 1) => Some(SystemClauseType::EnqueueAttributedVar),
- (atom!("$partial_string_tail"), 2) => Some(SystemClauseType::PartialStringTail),
- (atom!("$peek_byte"), 2) => Some(SystemClauseType::PeekByte),
- (atom!("$peek_char"), 2) => Some(SystemClauseType::PeekChar),
- (atom!("$peek_code"), 2) => Some(SystemClauseType::PeekCode),
- (atom!("$is_partial_string"), 1) => Some(SystemClauseType::IsPartialString),
- (atom!("$fetch_global_var"), 2) => Some(SystemClauseType::FetchGlobalVar),
- (atom!("$get_byte"), 2) => Some(SystemClauseType::GetByte),
- (atom!("$get_char"), 2) => Some(SystemClauseType::GetChar),
- (atom!("$get_n_chars"), 3) => Some(SystemClauseType::GetNChars),
- (atom!("$get_code"), 2) => Some(SystemClauseType::GetCode),
- (atom!("$get_single_char"), 1) => Some(SystemClauseType::GetSingleChar),
- (atom!("$points_to_cont_reset_marker"), 1) => {
- Some(SystemClauseType::PointsToContinuationResetMarker)
- }
- (atom!("$put_byte"), 2) => Some(SystemClauseType::PutByte),
- (atom!("$put_char"), 2) => Some(SystemClauseType::PutChar),
- (atom!("$put_chars"), 2) => Some(SystemClauseType::PutChars),
- (atom!("$put_code"), 2) => Some(SystemClauseType::PutCode),
- (atom!("$reset_attr_var_state"), 0) => Some(SystemClauseType::ResetAttrVarState),
- (atom!("$truncate_if_no_lh_growth"), 1) => {
- Some(SystemClauseType::TruncateIfNoLiftedHeapGrowth)
- }
- (atom!("$truncate_if_no_lh_growth_diff"), 2) => {
- Some(SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff)
- }
- (atom!("$get_attr_list"), 2) => Some(SystemClauseType::GetAttributedVariableList),
- (atom!("$get_b_value"), 1) => Some(SystemClauseType::GetBValue),
- (atom!("$get_lh_from_offset"), 2) => Some(SystemClauseType::GetLiftedHeapFromOffset),
- (atom!("$get_lh_from_offset_diff"), 3) => Some(SystemClauseType::GetLiftedHeapFromOffsetDiff),
- (atom!("$get_double_quotes"), 1) => Some(SystemClauseType::GetDoubleQuotes),
- (atom!("$get_scc_cleaner"), 1) => Some(SystemClauseType::GetSCCCleaner),
- (atom!("$halt"), 1) => Some(SystemClauseType::Halt),
- (atom!("$head_is_dynamic"), 2) => Some(SystemClauseType::HeadIsDynamic),
- (atom!("$install_scc_cleaner"), 2) => Some(SystemClauseType::InstallSCCCleaner),
- (atom!("$install_inference_counter"), 3) => Some(SystemClauseType::InstallInferenceCounter),
- (atom!("$lh_length"), 1) => Some(SystemClauseType::LiftedHeapLength),
- (atom!("$maybe"), 0) => Some(SystemClauseType::Maybe),
- (atom!("$cpu_now"), 1) => Some(SystemClauseType::CpuNow),
- (atom!("$current_time"), 1) => Some(SystemClauseType::CurrentTime),
- (atom!("$module_exists"), 1) => Some(SystemClauseType::ModuleExists),
- (atom!("$no_such_predicate"), 2) => Some(SystemClauseType::NoSuchPredicate),
- (atom!("$number_to_chars"), 2) => Some(SystemClauseType::NumberToChars),
- (atom!("$number_to_codes"), 2) => Some(SystemClauseType::NumberToCodes),
- (atom!("$op"), 3) => Some(SystemClauseType::OpDeclaration),
- (atom!("$open"), 7) => Some(SystemClauseType::Open),
- (atom!("$set_stream_options"), 5) => Some(SystemClauseType::SetStreamOptions),
- (atom!("$redo_attr_var_binding"), 2) => Some(SystemClauseType::RedoAttrVarBinding),
- (atom!("$remove_call_policy_check"), 1) => Some(SystemClauseType::RemoveCallPolicyCheck),
- (atom!("$remove_inference_counter"), 2) => Some(SystemClauseType::RemoveInferenceCounter),
- (atom!("$restore_cut_policy"), 0) => Some(SystemClauseType::RestoreCutPolicy),
- (atom!("$set_cp"), 1) => Some(SystemClauseType::SetCutPoint(temp_v!(1))),
- (atom!("$set_input"), 1) => Some(SystemClauseType::SetInput),
- (atom!("$set_output"), 1) => Some(SystemClauseType::SetOutput),
- (atom!("$stream_property"), 3) => Some(SystemClauseType::StreamProperty),
- (atom!("$set_stream_position"), 2) => Some(SystemClauseType::SetStreamPosition),
- (atom!("$inference_level"), 2) => Some(SystemClauseType::InferenceLevel),
- (atom!("$clean_up_block"), 1) => Some(SystemClauseType::CleanUpBlock),
- (atom!("$erase_ball"), 0) => Some(SystemClauseType::EraseBall),
- (atom!("$fail"), 0) => Some(SystemClauseType::Fail),
- (atom!("$get_attr_var_queue_beyond"), 2) => Some(SystemClauseType::GetAttrVarQueueBeyond),
- (atom!("$get_attr_var_queue_delim"), 1) => Some(SystemClauseType::GetAttrVarQueueDelimiter),
- (atom!("$get_ball"), 1) => Some(SystemClauseType::GetBall),
- (atom!("$get_cont_chunk"), 3) => Some(SystemClauseType::GetContinuationChunk),
- (atom!("$get_current_block"), 1) => Some(SystemClauseType::GetCurrentBlock),
- (atom!("$get_cp"), 1) => Some(SystemClauseType::GetCutPoint),
- (atom!("$get_staggered_cp"), 1) => Some(SystemClauseType::GetStaggeredCutPoint),
- (atom!("$install_new_block"), 1) => Some(SystemClauseType::InstallNewBlock),
- (atom!("$quoted_token"), 1) => Some(SystemClauseType::QuotedToken),
- (atom!("$nextEP"), 3) => Some(SystemClauseType::NextEP),
- (atom!("$read_query_term"), 5) => Some(SystemClauseType::ReadQueryTerm),
- (atom!("$read_term"), 5) => Some(SystemClauseType::ReadTerm),
- (atom!("$read_term_from_chars"), 2) => Some(SystemClauseType::ReadTermFromChars),
- (atom!("$reset_block"), 1) => Some(SystemClauseType::ResetBlock),
- (atom!("$reset_cont_marker"), 0) => Some(SystemClauseType::ResetContinuationMarker),
- (atom!("$return_from_verify_attr"), 0) => Some(SystemClauseType::ReturnFromVerifyAttr),
- (atom!("$set_ball"), 1) => Some(SystemClauseType::SetBall),
- (atom!("$set_cp_by_default"), 1) => Some(SystemClauseType::SetCutPointByDefault(temp_v!(1))),
- (atom!("$set_double_quotes"), 1) => Some(SystemClauseType::SetDoubleQuotes),
- (atom!("$set_seed"), 1) => Some(SystemClauseType::SetSeed),
- (atom!("$skip_max_list"), 4) => Some(SystemClauseType::SkipMaxList),
- (atom!("$sleep"), 1) => Some(SystemClauseType::Sleep),
- (atom!("$tls_accept_client"), 4) => Some(SystemClauseType::TLSAcceptClient),
- (atom!("$tls_client_connect"), 3) => Some(SystemClauseType::TLSClientConnect),
- (atom!("$socket_client_open"), 8) => Some(SystemClauseType::SocketClientOpen),
- (atom!("$socket_server_open"), 3) => Some(SystemClauseType::SocketServerOpen),
- (atom!("$socket_server_accept"), 7) => Some(SystemClauseType::SocketServerAccept),
- (atom!("$socket_server_close"), 1) => Some(SystemClauseType::SocketServerClose),
- (atom!("$store_global_var"), 2) => Some(SystemClauseType::StoreGlobalVar),
- (atom!("$store_backtrackable_global_var"), 2) => {
- Some(SystemClauseType::StoreBacktrackableGlobalVar)
- }
- (atom!("$term_attributed_variables"), 2) => Some(SystemClauseType::TermAttributedVariables),
- (atom!("$term_variables"), 2) => Some(SystemClauseType::TermVariables),
- (atom!("$term_variables_under_max_depth"), 3) => Some(SystemClauseType::TermVariablesUnderMaxDepth),
- (atom!("$truncate_lh_to"), 1) => Some(SystemClauseType::TruncateLiftedHeapTo),
- (atom!("$unwind_environments"), 0) => Some(SystemClauseType::UnwindEnvironments),
- (atom!("$unwind_stack"), 0) => Some(SystemClauseType::UnwindStack),
- (atom!("$unify_with_occurs_check"), 2) => Some(SystemClauseType::UnifyWithOccursCheck),
- (atom!("$directory_files"), 2) => Some(SystemClauseType::DirectoryFiles),
- (atom!("$file_size"), 2) => Some(SystemClauseType::FileSize),
- (atom!("$file_exists"), 1) => Some(SystemClauseType::FileExists),
- (atom!("$directory_exists"), 1) => Some(SystemClauseType::DirectoryExists),
- (atom!("$directory_separator"), 1) => Some(SystemClauseType::DirectorySeparator),
- (atom!("$make_directory"), 1) => Some(SystemClauseType::MakeDirectory),
- (atom!("$make_directory_path"), 1) => Some(SystemClauseType::MakeDirectoryPath),
- (atom!("$delete_file"), 1) => Some(SystemClauseType::DeleteFile),
- (atom!("$rename_file"), 2) => Some(SystemClauseType::RenameFile),
- (atom!("$delete_directory"), 1) => Some(SystemClauseType::DeleteDirectory),
- (atom!("$working_directory"), 2) => Some(SystemClauseType::WorkingDirectory),
- (atom!("$path_canonical"), 2) => Some(SystemClauseType::PathCanonical),
- (atom!("$file_time"), 3) => Some(SystemClauseType::FileTime),
- (atom!("$clause_to_evacuable"), 2) => {
- Some(SystemClauseType::REPL(REPLCodePtr::ClauseToEvacuable))
- }
- (atom!("$scoped_clause_to_evacuable"), 3) => {
- Some(SystemClauseType::REPL(REPLCodePtr::ScopedClauseToEvacuable))
- }
- (atom!("$conclude_load"), 1) => Some(SystemClauseType::REPL(REPLCodePtr::ConcludeLoad)),
- (atom!("$use_module"), 3) => Some(SystemClauseType::REPL(REPLCodePtr::UseModule)),
- (atom!("$declare_module"), 3) => Some(SystemClauseType::REPL(REPLCodePtr::DeclareModule)),
- (atom!("$load_compiled_library"), 3) => {
- Some(SystemClauseType::REPL(REPLCodePtr::LoadCompiledLibrary))
- }
- (atom!("$push_load_state_payload"), 1) => {
- Some(SystemClauseType::REPL(REPLCodePtr::PushLoadStatePayload))
- }
- (atom!("$add_in_situ_filename_module"), 1) => {
- Some(SystemClauseType::REPL(REPLCodePtr::AddInSituFilenameModule))
- }
- (atom!("$asserta"), 5) => Some(SystemClauseType::REPL(REPLCodePtr::Asserta)),
- (atom!("$assertz"), 5) => Some(SystemClauseType::REPL(REPLCodePtr::Assertz)),
- (atom!("$retract_clause"), 4) => Some(SystemClauseType::REPL(REPLCodePtr::Retract)),
- (atom!("$is_consistent_with_term_queue"), 4) => Some(SystemClauseType::REPL(
- REPLCodePtr::IsConsistentWithTermQueue,
- )),
- (atom!("$flush_term_queue"), 1) => Some(SystemClauseType::REPL(REPLCodePtr::FlushTermQueue)),
- (atom!("$remove_module_exports"), 2) => {
- Some(SystemClauseType::REPL(REPLCodePtr::RemoveModuleExports))
- }
- (atom!("$add_non_counted_backtracking"), 3) => Some(SystemClauseType::REPL(
- REPLCodePtr::AddNonCountedBacktracking,
- )),
- (atom!("$wam_instructions"), 4) => Some(SystemClauseType::WAMInstructions),
- (atom!("$write_term"), 7) => Some(SystemClauseType::WriteTerm),
- (atom!("$write_term_to_chars"), 7) => Some(SystemClauseType::WriteTermToChars),
- (atom!("$scryer_prolog_version"), 1) => Some(SystemClauseType::ScryerPrologVersion),
- (atom!("$crypto_random_byte"), 1) => Some(SystemClauseType::CryptoRandomByte),
- (atom!("$crypto_data_hash"), 4) => Some(SystemClauseType::CryptoDataHash),
- (atom!("$crypto_data_hkdf"), 7) => Some(SystemClauseType::CryptoDataHKDF),
- (atom!("$crypto_password_hash"), 4) => Some(SystemClauseType::CryptoPasswordHash),
- (atom!("$crypto_data_encrypt"), 7) => Some(SystemClauseType::CryptoDataEncrypt),
- (atom!("$crypto_data_decrypt"), 6) => Some(SystemClauseType::CryptoDataDecrypt),
- (atom!("$crypto_curve_scalar_mult"), 5) => Some(SystemClauseType::CryptoCurveScalarMult),
- (atom!("$ed25519_sign"), 4) => Some(SystemClauseType::Ed25519Sign),
- (atom!("$ed25519_verify"), 4) => Some(SystemClauseType::Ed25519Verify),
- (atom!("$ed25519_new_keypair"), 1) => Some(SystemClauseType::Ed25519NewKeyPair),
- (atom!("$ed25519_keypair_public_key"), 2) => Some(SystemClauseType::Ed25519KeyPairPublicKey),
- (atom!("$curve25519_scalar_mult"), 3) => Some(SystemClauseType::Curve25519ScalarMult),
- (atom!("$first_non_octet"), 2) => Some(SystemClauseType::FirstNonOctet),
- (atom!("$load_html"), 3) => Some(SystemClauseType::LoadHTML),
- (atom!("$load_xml"), 3) => Some(SystemClauseType::LoadXML),
- (atom!("$getenv"), 2) => Some(SystemClauseType::GetEnv),
- (atom!("$setenv"), 2) => Some(SystemClauseType::SetEnv),
- (atom!("$unsetenv"), 1) => Some(SystemClauseType::UnsetEnv),
- (atom!("$shell"), 2) => Some(SystemClauseType::Shell),
- (atom!("$pid"), 1) => Some(SystemClauseType::PID),
- (atom!("$chars_base64"), 4) => Some(SystemClauseType::CharsBase64),
- (atom!("$load_library_as_stream"), 3) => Some(SystemClauseType::LoadLibraryAsStream),
- (atom!("$push_load_context"), 2) => Some(SystemClauseType::REPL(REPLCodePtr::PushLoadContext)),
- (atom!("$pop_load_state_payload"), 1) => {
- Some(SystemClauseType::REPL(REPLCodePtr::PopLoadStatePayload))
- }
- (atom!("$pop_load_context"), 0) => Some(SystemClauseType::REPL(REPLCodePtr::PopLoadContext)),
- (atom!("$prolog_lc_source"), 1) => {
- Some(SystemClauseType::REPL(REPLCodePtr::LoadContextSource))
- }
- (atom!("$prolog_lc_file"), 1) => Some(SystemClauseType::REPL(REPLCodePtr::LoadContextFile)),
- (atom!("$prolog_lc_dir"), 1) => {
- Some(SystemClauseType::REPL(REPLCodePtr::LoadContextDirectory))
- }
- (atom!("$prolog_lc_module"), 1) => {
- Some(SystemClauseType::REPL(REPLCodePtr::LoadContextModule))
- }
- (atom!("$prolog_lc_stream"), 1) => {
- Some(SystemClauseType::REPL(REPLCodePtr::LoadContextStream))
- }
- (atom!("$cpp_meta_predicate_property"), 4) => {
- Some(SystemClauseType::REPL(REPLCodePtr::MetaPredicateProperty))
- }
- (atom!("$cpp_built_in_property"), 2) => {
- Some(SystemClauseType::REPL(REPLCodePtr::BuiltInProperty))
- }
- (atom!("$cpp_dynamic_property"), 3) => {
- Some(SystemClauseType::REPL(REPLCodePtr::DynamicProperty))
- }
- (atom!("$cpp_multifile_property"), 3) => {
- Some(SystemClauseType::REPL(REPLCodePtr::MultifileProperty))
- }
- (atom!("$cpp_discontiguous_property"), 3) => {
- Some(SystemClauseType::REPL(REPLCodePtr::DiscontiguousProperty))
- }
- (atom!("$devour_whitespace"), 1) => Some(SystemClauseType::DevourWhitespace),
- (atom!("$is_sto_enabled"), 1) => Some(SystemClauseType::IsSTOEnabled),
- (atom!("$set_sto_as_unify"), 0) => Some(SystemClauseType::SetSTOAsUnify),
- (atom!("$set_nsto_as_unify"), 0) => Some(SystemClauseType::SetNSTOAsUnify),
- (atom!("$set_sto_with_error_as_unify"), 0) => Some(SystemClauseType::SetSTOWithErrorAsUnify),
- (atom!("$home_directory"), 1) => Some(SystemClauseType::HomeDirectory),
- (atom!("$debug_hook"), 0) => Some(SystemClauseType::DebugHook),
- (atom!("$popcount"), 2) => Some(SystemClauseType::PopCount),
- _ => None,
- }
- }
-}
-
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub enum BuiltInClauseType {
- AcyclicTerm,
- Arg,
- Compare,
- CompareTerm(CompareTermQT),
- CopyTerm,
- Eq,
- Functor,
- Ground,
- Is(RegType, ArithmeticTerm),
- KeySort,
- NotEq,
- Read,
- Sort,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum ClauseType {
- BuiltIn(BuiltInClauseType),
- CallN,
- Inlined(InlinedClauseType),
- Named(Atom, usize, CodeIndex), // name, arity, index.
- System(SystemClauseType),
-}
-
-impl BuiltInClauseType {
- pub(crate) fn name(&self) -> Atom {
- match self {
- &BuiltInClauseType::AcyclicTerm => atom!("acyclic_term"),
- &BuiltInClauseType::Arg => atom!("arg"),
- &BuiltInClauseType::Compare => atom!("compare"),
- &BuiltInClauseType::CompareTerm(qt) => qt.name(),
- &BuiltInClauseType::CopyTerm => atom!("copy_term"),
- &BuiltInClauseType::Eq => atom!("=="),
- &BuiltInClauseType::Functor => atom!("functor"),
- &BuiltInClauseType::Ground => atom!("ground"),
- &BuiltInClauseType::Is(..) => atom!("is"),
- &BuiltInClauseType::KeySort => atom!("keysort"),
- &BuiltInClauseType::NotEq => atom!("\\=="),
- &BuiltInClauseType::Read => atom!("read"),
- &BuiltInClauseType::Sort => atom!("sort"),
- }
- }
-
- pub(crate) fn arity(&self) -> usize {
- match self {
- &BuiltInClauseType::AcyclicTerm => 1,
- &BuiltInClauseType::Arg => 3,
- &BuiltInClauseType::Compare => 2,
- &BuiltInClauseType::CompareTerm(_) => 2,
- &BuiltInClauseType::CopyTerm => 2,
- &BuiltInClauseType::Eq => 2,
- &BuiltInClauseType::Functor => 3,
- &BuiltInClauseType::Ground => 1,
- &BuiltInClauseType::Is(..) => 2,
- &BuiltInClauseType::KeySort => 2,
- &BuiltInClauseType::NotEq => 2,
- &BuiltInClauseType::Read => 1,
- &BuiltInClauseType::Sort => 2,
- }
- }
-}
-
-impl ClauseType {
- pub(crate) fn name(&self) -> Atom {
- match self {
- &ClauseType::BuiltIn(ref built_in) => built_in.name(),
- &ClauseType::CallN => atom!("$call"),
- &ClauseType::Inlined(ref inlined) => inlined.name(),
- &ClauseType::Named(name, ..) => name,
- &ClauseType::System(ref system) => system.name(),
- }
- }
-
- pub(crate) fn from(name: Atom, arity: usize) -> Self {
- clause_type_form(name, arity).unwrap_or_else(|| {
- SystemClauseType::from(name, arity)
- .map(ClauseType::System)
- .unwrap_or_else(|| {
- if name == atom!("$call") {
- ClauseType::CallN
- } else {
- ClauseType::Named(name, arity, CodeIndex::default())
- }
- })
- })
- }
-}
-
-impl From<InlinedClauseType> for ClauseType {
- fn from(inlined_ct: InlinedClauseType) -> Self {
- ClauseType::Inlined(inlined_ct)
- }
-}
use crate::allocator::*;
use crate::arithmetic::*;
-use crate::clause_types::*;
use crate::fixtures::*;
use crate::forms::*;
use crate::indexing::*;
use crate::targets::*;
use crate::types::*;
+use crate::instr;
use crate::machine::machine_errors::*;
use indexmap::{IndexMap, IndexSet};
let mut code_index = 0;
for phase in 0.. {
- while let Line::Query(ref query_instr) = &code[code_index] {
+ while code[code_index].is_query_instr() {
+ let query_instr = &mut code[code_index];
+
if !unsafe_var_marker.mark_safe_vars(query_instr) {
unsafe_var_marker.mark_phase(query_instr, phase);
}
code_index = 0;
for phase in 0.. {
- while let Line::Query(ref mut query_instr) = &mut code[code_index] {
+ while code[code_index].is_query_instr() {
+ let query_instr = &mut code[code_index];
unsafe_var_marker.mark_unsafe_vars(query_instr, phase);
code_index += 1;
}
}
#[inline]
- pub(crate) fn internal_try_me_else(&self, offset: usize) -> ChoiceInstruction {
+ pub(crate) fn internal_try_me_else(&self, offset: usize) -> Instruction {
if let Some(global_clock_time) = self.global_clock_tick {
- ChoiceInstruction::DynamicInternalElse(
+ Instruction::DynamicInternalElse(
global_clock_time,
Death::Infinity,
if offset == 0 {
},
)
} else {
- ChoiceInstruction::TryMeElse(offset)
+ Instruction::TryMeElse(offset)
}
}
- pub(crate) fn try_me_else(&self, offset: usize) -> ChoiceInstruction {
+ pub(crate) fn try_me_else(&self, offset: usize) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
- ChoiceInstruction::DynamicElse(
+ Instruction::DynamicElse(
global_clock_tick,
Death::Infinity,
if offset == 0 {
},
)
} else {
- ChoiceInstruction::TryMeElse(offset)
+ Instruction::TryMeElse(offset)
}
}
- pub(crate) fn internal_retry_me_else(&self, offset: usize) -> ChoiceInstruction {
+ pub(crate) fn internal_retry_me_else(&self, offset: usize) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
- ChoiceInstruction::DynamicInternalElse(
+ Instruction::DynamicInternalElse(
global_clock_tick,
Death::Infinity,
if offset == 0 {
},
)
} else {
- ChoiceInstruction::RetryMeElse(offset)
+ Instruction::RetryMeElse(offset)
}
}
- pub(crate) fn retry_me_else(&self, offset: usize) -> ChoiceInstruction {
+ pub(crate) fn retry_me_else(&self, offset: usize) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
- ChoiceInstruction::DynamicElse(
+ Instruction::DynamicElse(
global_clock_tick,
Death::Infinity,
if offset == 0 {
},
)
} else if self.non_counted_bt {
- ChoiceInstruction::DefaultRetryMeElse(offset)
+ Instruction::DefaultRetryMeElse(offset)
} else {
- ChoiceInstruction::RetryMeElse(offset)
+ Instruction::RetryMeElse(offset)
}
}
- pub(crate) fn internal_trust_me(&self) -> ChoiceInstruction {
+ pub(crate) fn internal_trust_me(&self) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
- ChoiceInstruction::DynamicInternalElse(
+ Instruction::DynamicInternalElse(
global_clock_tick,
Death::Infinity,
NextOrFail::Fail(0),
)
} else if self.non_counted_bt {
- ChoiceInstruction::DefaultTrustMe(0)
+ Instruction::DefaultTrustMe(0)
} else {
- ChoiceInstruction::TrustMe(0)
+ Instruction::TrustMe(0)
}
}
- pub(crate) fn trust_me(&self) -> ChoiceInstruction {
+ pub(crate) fn trust_me(&self) -> Instruction {
if let Some(global_clock_tick) = self.global_clock_tick {
- ChoiceInstruction::DynamicElse(global_clock_tick, Death::Infinity, NextOrFail::Fail(0))
+ Instruction::DynamicElse(global_clock_tick, Death::Infinity, NextOrFail::Fail(0))
} else if self.non_counted_bt {
- ChoiceInstruction::DefaultTrustMe(0)
+ Instruction::DefaultTrustMe(0)
} else {
- ChoiceInstruction::TrustMe(0)
+ Instruction::TrustMe(0)
}
}
}
vr: &'a Cell<VarReg>,
code: &mut Code,
) -> RegType {
- let mut target = Vec::new();
- self.marker
- .mark_var(name, Level::Shallow, vr, term_loc, &mut target);
+ let mut target = Code::new();
+ self.marker.mark_var::<QueryInstruction>(name, Level::Shallow, vr, term_loc, &mut target);
if !target.is_empty() {
- code.extend(target.into_iter().map(Line::Query));
+ code.extend(target.into_iter());
}
vr.get().norm()
}
}
- fn add_or_increment_void_instr<Target>(target: &mut Vec<Target>)
+ fn add_or_increment_void_instr<Target>(target: &mut Code)
where
Target: crate::targets::CompilationTarget<'a>,
{
var: &'a Rc<String>,
term_loc: GenContext,
is_exposed: bool,
- target: &mut Vec<Target>,
+ target: &mut Code,
) {
if is_exposed || self.get_var_count(var.as_ref()) > 1 {
- self.marker
- .mark_var(var.clone(), Level::Deep, cell, term_loc, target);
+ self.marker.mark_var::<Target>(var.clone(), Level::Deep, cell, term_loc, target);
} else {
- Self::add_or_increment_void_instr(target);
+ Self::add_or_increment_void_instr::<Target>(target);
}
}
subterm: &'a Term,
term_loc: GenContext,
is_exposed: bool,
- target: &mut Vec<Target>,
+ target: &mut Code,
) {
match subterm {
&Term::AnonVar if is_exposed => {
- self.marker.mark_anon_var(Level::Deep, term_loc, target);
+ self.marker.mark_anon_var::<Target>(Level::Deep, term_loc, target);
}
&Term::AnonVar => {
- Self::add_or_increment_void_instr(target);
+ Self::add_or_increment_void_instr::<Target>(target);
}
&Term::Cons(ref cell, ..)
| &Term::Clause(ref cell, ..)
| Term::PartialString(ref cell, ..) => {
- self.marker
- .mark_non_var(Level::Deep, term_loc, cell, target);
+ self.marker.mark_non_var::<Target>(Level::Deep, term_loc, cell, target);
target.push(Target::clause_arg_to_instr(cell.get()));
}
&Term::Literal(_, ref constant) => {
target.push(Target::constant_subterm(constant.clone()));
}
&Term::Var(ref cell, ref var) => {
- self.deep_var_instr(cell, var, term_loc, is_exposed, target);
+ self.deep_var_instr::<Target>(cell, var, term_loc, is_exposed, target);
}
};
}
iter: Iter,
term_loc: GenContext,
is_exposed: bool,
- ) -> Vec<Target>
+ ) -> Code
where
Target: crate::targets::CompilationTarget<'a>,
Iter: Iterator<Item = TermRef<'a>>,
{
- let mut target = Vec::new();
+ let mut target: Code = Vec::new();
for term in iter {
match term {
if let GenContext::Head = term_loc {
self.marker.advance_arg();
} else {
- self.marker.mark_anon_var(lvl, term_loc, &mut target);
+ self.marker.mark_anon_var::<Target>(lvl, term_loc, &mut target);
}
}
TermRef::Clause(lvl, cell, ct, terms) => {
- self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
- target.push(Target::to_structure(ct, terms.len(), cell.get()));
+ self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
+ target.push(Target::to_structure(ct.name(), terms.len(), cell.get()));
for subterm in terms {
- self.subterm_to_instr(subterm, term_loc, is_exposed, &mut target);
+ self.subterm_to_instr::<Target>(subterm, term_loc, is_exposed, &mut target);
}
}
TermRef::Cons(lvl, cell, head, tail) => {
- self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
+ self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_list(lvl, cell.get()));
- self.subterm_to_instr(head, term_loc, is_exposed, &mut target);
- self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
+ self.subterm_to_instr::<Target>(head, term_loc, is_exposed, &mut target);
+ self.subterm_to_instr::<Target>(tail, term_loc, is_exposed, &mut target);
}
TermRef::Literal(lvl @ Level::Shallow, cell, Literal::String(ref string)) => {
- self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
+ self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_pstr(lvl, *string, cell.get(), false));
}
TermRef::Literal(lvl @ Level::Shallow, cell, constant) => {
- self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
+ self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_constant(lvl, *constant, cell.get()));
}
TermRef::PartialString(lvl, cell, string, tail) => {
- self.marker.mark_non_var(lvl, term_loc, cell, &mut target);
+ self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
if let Some(tail) = tail {
target.push(Target::to_pstr(lvl, string, cell.get(), true));
- self.subterm_to_instr(tail, term_loc, is_exposed, &mut target);
+ self.subterm_to_instr::<Target>(tail, term_loc, is_exposed, &mut target);
} else {
target.push(Target::to_pstr(lvl, string, cell.get(), false));
}
TermRef::Var(lvl @ Level::Shallow, cell, ref var) if var.as_str() == "!" => {
if self.marker.is_unbound(var.clone()) {
if term_loc != GenContext::Head {
- self.marker.mark_reserved_var(
+ self.marker.mark_reserved_var::<Target>(
var.clone(),
lvl,
cell,
}
}
- self.marker
- .mark_var(var.clone(), lvl, cell, term_loc, &mut target);
+ self.marker.mark_var::<Target>(var.clone(), lvl, cell, term_loc, &mut target);
}
TermRef::Var(lvl @ Level::Shallow, cell, var) => {
- self.marker
- .mark_var(var.clone(), lvl, cell, term_loc, &mut target);
+ self.marker.mark_var::<Target>(var.clone(), lvl, cell, term_loc, &mut target);
}
_ => {}
};
match qt {
&QueryTerm::Jump(ref vars) => {
self.jmp_by_locs.push(code.len());
- code.push(jmp_call!(vars.len(), 0, pvs));
+ code.push(instr!("jmp_by_call", vars.len(), 0, pvs));
}
- &QueryTerm::Clause(_, ref ct, ref terms, true) => {
- code.push(call_clause_by_default!(ct.clone(), terms.len(), pvs));
+ &QueryTerm::Clause(_, ref ct, _, true) => {
+ code.push(call_clause_by_default!(ct.clone(), pvs));
}
- &QueryTerm::Clause(_, ref ct, ref terms, false) => {
- code.push(call_clause!(ct.clone(), terms.len(), pvs));
+ &QueryTerm::Clause(_, ref ct, _, false) => {
+ code.push(call_clause!(ct.clone(), pvs));
}
_ => {}
}
fn lco(code: &mut Code) -> usize {
let mut dealloc_index = code.len() - 1;
+ let last_instr = code.pop();
- match code.last_mut() {
- Some(&mut Line::Control(ref mut ctrl)) => match ctrl {
- &mut ControlInstruction::CallClause(_, _, _, ref mut last_call, _) => {
- *last_call = true;
- }
- &mut ControlInstruction::JmpBy(_, _, _, ref mut last_call) => {
- *last_call = true;
- }
- &mut ControlInstruction::Proceed => {}
- _ => {
- dealloc_index += 1;
- }
- },
- Some(&mut Line::Cut(CutInstruction::Cut(_))) => {
+ match last_instr {
+ Some(instr @ Instruction::Proceed) => {
+ code.push(instr);
+ }
+ Some(instr @ Instruction::Cut(_)) => {
dealloc_index += 1;
+ code.push(instr);
}
- _ => {}
- };
+ Some(mut instr) if instr.is_ctrl_instr() => {
+ code.push(if instr.perm_vars_mut().is_some() {
+ instr.to_execute()
+ } else {
+ dealloc_index += 1;
+ instr
+ });
+ }
+ Some(instr) => {
+ code.push(instr);
+ }
+ None => {}
+ }
dealloc_index
}
code: &mut Code,
) -> Result<(), CompilationError> {
match ct {
- &InlinedClauseType::CompareNumber(cmp, ..) => {
+ &InlinedClauseType::CompareNumber(mut cmp) => {
self.marker.reset_arg(2);
let (mut lcode, at_1) = self.call_arith_eval(&terms[0], 1)?;
&Term::Literal(_, Literal::Char(_))
| &Term::Literal(_, Literal::Atom(atom!("[]")))
| &Term::Literal(_, Literal::Atom(..)) => {
- code.push(succeed!());
+ code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
- code.push(is_atom!(r));
+ code.push(instr!("atom", r, 0));
}
_ => {
- code.push(fail!());
+ code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsAtomic(..) => match &terms[0] {
&Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) | &Term::PartialString(..) => {
- code.push(fail!());
+ code.push(instr!("$fail", 0));
}
&Term::Literal(_, Literal::String(_)) => {
- code.push(fail!());
+ code.push(instr!("$fail", 0));
}
&Term::Literal(..) => {
- code.push(succeed!());
+ code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
- code.push(is_atomic!(r));
+ code.push(instr!("atomic", r, 0));
}
},
&InlinedClauseType::IsCompound(..) => match &terms[0] {
&Term::Clause(..) | &Term::Cons(..) | &Term::PartialString(..) |
&Term::Literal(_, Literal::String(..)) => {
- code.push(succeed!());
+ code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
- code.push(is_compound!(r));
+ code.push(instr!("compound", r, 0));
}
_ => {
- code.push(fail!());
+ code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsRational(..) => match &terms[0] {
&Term::Literal(_, Literal::Rational(_)) => {
- code.push(succeed!());
+ code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
- code.push(is_rational!(r));
+ code.push(instr!("rational", r, 0));
}
_ => {
- code.push(fail!());
+ code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsFloat(..) => match &terms[0] {
&Term::Literal(_, Literal::Float(_)) => {
- code.push(succeed!());
+ code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
- code.push(is_float!(r));
+ code.push(instr!("float", r, 0));
}
_ => {
- code.push(fail!());
+ code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsNumber(..) => match &terms[0] {
| &Term::Literal(_, Literal::Rational(_))
| &Term::Literal(_, Literal::Integer(_))
| &Term::Literal(_, Literal::Fixnum(_)) => {
- code.push(succeed!());
+ code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
- code.push(is_number!(r));
+ code.push(instr!("number", r, 0));
}
_ => {
- code.push(fail!());
+ code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsNonVar(..) => match &terms[0] {
&Term::AnonVar => {
- code.push(fail!());
+ code.push(instr!("$fail", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
- code.push(is_nonvar!(r));
+ code.push(instr!("nonvar", r, 0));
}
_ => {
- code.push(succeed!());
+ code.push(instr!("$succeed", 0));
}
},
&InlinedClauseType::IsInteger(..) => match &terms[0] {
&Term::Literal(_, Literal::Integer(_)) | &Term::Literal(_, Literal::Fixnum(_)) => {
- code.push(succeed!());
+ code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
- code.push(is_integer!(r));
+ code.push(instr!("integer", r, 0));
}
_ => {
- code.push(fail!());
+ code.push(instr!("$fail", 0));
}
},
&InlinedClauseType::IsVar(..) => match &terms[0] {
| &Term::Clause(..)
| &Term::Cons(..)
| &Term::PartialString(..) => {
- code.push(fail!());
+ code.push(instr!("$fail", 0));
}
&Term::AnonVar => {
- code.push(succeed!());
+ code.push(instr!("$succeed", 0));
}
&Term::Var(ref vr, ref name) => {
self.marker.reset_arg(1);
let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code);
- code.push(is_var!(r));
+ code.push(instr!("var", r, 0));
}
},
}
&Term::Var(ref vr, ref name) => {
let mut target = vec![];
- self.marker
- .mark_var(name.clone(), Level::Shallow, vr, term_loc, &mut target);
+ self.marker.mark_var::<QueryInstruction>(
+ name.clone(),
+ Level::Shallow,
+ vr,
+ term_loc,
+ &mut target,
+ );
if !target.is_empty() {
- code.extend(target.into_iter().map(Line::Query));
+ code.extend(target.into_iter());
}
}
&Term::Literal(_, c @ Literal::Integer(_))
| &Term::Literal(_, c @ Literal::Fixnum(_)) => {
let v = HeapCellValue::from(c);
- code.push(Line::Query(put_constant!(Level::Shallow, v, temp_v!(1))));
+ code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
self.marker.advance_arg();
}
&Term::Literal(_, c @ Literal::Float(_)) => {
let v = HeapCellValue::from(c);
- code.push(Line::Query(put_constant!(Level::Shallow, v, temp_v!(1))));
+ code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
self.marker.advance_arg();
}
&Term::Literal(_, c @ Literal::Rational(_)) => {
let v = HeapCellValue::from(c);
- code.push(Line::Query(put_constant!(Level::Shallow, v, temp_v!(1))));
+ code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
self.marker.advance_arg();
}
_ => {
- code.push(fail!());
+ code.push(instr!("$fail", 0));
return Ok(());
}
}
};
Ok(if use_default_call_policy {
- code.push(is_call_by_default!(temp_v!(1), at));
+ code.push(instr!("is", default, temp_v!(1), at, 0));
} else {
- code.push(is_call!(temp_v!(1), at));
+ code.push(instr!("is", temp_v!(1), at, 0));
})
}
fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &'a Cell<VarReg>) {
let r = self.marker.get(Rc::new(String::from("!")));
cell.set(VarReg::Norm(r));
- code.push(set_cp!(cell.get().norm()));
+ code.push(instr!("$set_cp", cell.get().norm(), 0));
}
fn compile_get_level_and_unify(
var: Rc<String>,
term_loc: GenContext,
) {
- let mut target = Vec::new();
+ let mut target = Code::new();
self.marker.reset_arg(1);
- self.marker
- .mark_var(var, Level::Shallow, cell, term_loc, &mut target);
+ self.marker.mark_var::<QueryInstruction>(var, Level::Shallow, cell, term_loc, &mut target);
if !target.is_empty() {
- code.extend(
- target
- .into_iter()
- .map(|query_instr| Line::Query(query_instr)),
- );
+ code.extend(target.into_iter());
}
- code.push(get_level_and_unify!(cell.get().norm()));
+ code.push(instr!("get_level_and_unify", cell.get().norm()));
}
fn compile_seq(
}
&QueryTerm::UnblockedCut(ref cell) => self.compile_unblocked_cut(code, cell),
&QueryTerm::BlockedCut => code.push(if chunk_num == 0 {
- Line::Cut(CutInstruction::NeckCut)
+ Instruction::NeckCut
} else {
- Line::Cut(CutInstruction::Cut(perm_v!(1)))
+ Instruction::Cut(perm_v!(1))
}),
&QueryTerm::Clause(
_,
if conjunct_info.allocates() {
let perm_vars = conjunct_info.perm_vars();
- body.push(Line::Control(ControlInstruction::Allocate(perm_vars)));
+ body.push(Instruction::Allocate(perm_vars));
if conjunct_info.has_deep_cut {
- body.push(Line::Cut(CutInstruction::GetLevel(perm_v!(1))));
+ body.push(Instruction::GetLevel(perm_v!(1)));
}
}
}
) {
// add a proceed to bookend any trailing cuts.
match toc {
- &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => code.push(proceed!()),
- &QueryTerm::Clause(_, ClauseType::Inlined(..), ..) => code.push(proceed!()),
+ &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => {
+ code.push(instr!("proceed"));
+ }
_ => {}
};
}
}
- code.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate));
+ code.insert(dealloc_index, instr!("deallocate"));
}
}
self.compile_seq_prelude(&conjunct_info, &mut code);
let iter = FactIterator::from_rule_head_clause(args);
- let mut fact = self.compile_target(iter, GenContext::Head, false);
+ let mut fact = self.compile_target::<FactInstruction, _>(iter, GenContext::Head, false);
let mut unsafe_var_marker = UnsafeVarMarker::new();
if !fact.is_empty() {
unsafe_var_marker = self.mark_unsafe_fact_vars(&mut fact);
-
- for fact_instr in fact {
- code.push(Line::Fact(fact_instr));
- }
+ code.extend(fact.into_iter());
}
let iter = ChunkedIterator::from_rule_body(p1, clauses);
Ok(code)
}
- fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact) -> UnsafeVarMarker {
+ fn mark_unsafe_fact_vars(&self, fact: &mut Code) -> UnsafeVarMarker {
let mut safe_vars = IndexSet::new();
for fact_instr in fact.iter_mut() {
match fact_instr {
- &mut FactInstruction::UnifyValue(r) => {
+ &mut Instruction::UnifyValue(r) => {
if !safe_vars.contains(&r) {
- *fact_instr = FactInstruction::UnifyLocalValue(r);
+ *fact_instr = Instruction::UnifyLocalValue(r);
safe_vars.insert(r);
}
}
- &mut FactInstruction::UnifyVariable(r) => {
+ &mut Instruction::UnifyVariable(r) => {
safe_vars.insert(r);
}
_ => {}
self.marker.reset_at_head(args);
let iter = FactInstruction::iter(term);
- let mut compiled_fact = self.compile_target(iter, GenContext::Head, false);
+ let mut compiled_fact = self.compile_target::<FactInstruction, _>(
+ iter,
+ GenContext::Head,
+ false,
+ );
self.mark_unsafe_fact_vars(&mut compiled_fact);
if !compiled_fact.is_empty() {
- for fact_instr in compiled_fact {
- code.push(Line::Fact(fact_instr));
- }
+ code.extend(compiled_fact.into_iter());
}
}
- code.push(proceed!());
+ code.push(instr!("proceed"));
code
}
self.marker.reset_arg(term.arity());
let iter = query_term_post_order_iter(term);
- let query = self.compile_target(iter, term_loc, is_exposed);
+ let query = self.compile_target::<QueryInstruction, _>(iter, term_loc, is_exposed);
if !query.is_empty() {
- for query_instr in query {
- code.push(Line::Query(query_instr));
- }
+ code.extend(query.into_iter());
}
self.add_conditional_call(code, term, num_perm_vars_left);
if clauses.len() > 1 {
let choice = match i {
0 => self.settings.internal_try_me_else(clause_code.len() + 1),
- //ChoiceInstruction::TryMeElse(clause_code.len() + 1),
+ //Instruction::TryMeElse(clause_code.len() + 1),
_ if i == clauses.len() - 1 => self.settings.internal_trust_me(),
_ => self.settings.internal_retry_me_else(clause_code.len() + 1),
};
- code.push_back(Line::Choice(choice));
+ code.push_back(choice);
} else if self.settings.is_extensible {
/*
generate stub choice instructions for extensible
over them.
*/
- code.push_front(Line::Choice(self.settings.internal_try_me_else(0)));
- //Line::Choice(ChoiceInstruction::TryMeElse(0)));
- skip_stub_try_me_else = !self.settings.is_dynamic(); //true;
+ code.push_front(self.settings.internal_try_me_else(0));
+ skip_stub_try_me_else = !self.settings.is_dynamic();
}
let arg = match clause.args() {
self.global_jmp_by_locs_offset = jmp_by_locs_len;
if !index_code.is_empty() {
- code.push_front(Line::IndexingCode(index_code));
+ code.push_front(Instruction::IndexingCode(index_code));
if skip_stub_try_me_else {
// skip the TryMeElse(0) also.
_ => self.settings.retry_me_else(code_segment.len() + 1),
};
- code.push(Line::Choice(choice));
+ code.push(choice);
} else if self.settings.is_extensible {
- code.push(Line::Choice(self.settings.try_me_else(0)));
+ code.push(self.settings.try_me_else(0));
}
if self.settings.is_extensible {
- let segment_is_indexed = to_indexing_line(&code_segment[0]).is_some();
+ let segment_is_indexed = code_segment[0].to_indexing_line().is_some();
for clause_index_info in self.skeleton.clauses[skel_lower_bound..].iter_mut() {
clause_index_info.clause_start +=
use crate::allocator::*;
use crate::fixtures::*;
use crate::forms::Level;
+use crate::instructions::*;
use crate::machine::machine_indices::*;
use crate::parser::ast::*;
use crate::targets::CompilationTarget;
use crate::temp_v;
+use fxhash::FxBuildHasher;
+
use std::cell::Cell;
use std::collections::BTreeSet;
use std::rc::Rc;
#[derive(Debug)]
pub(crate) struct DebrayAllocator {
- bindings: IndexMap<Rc<String>, VarData>,
+ bindings: IndexMap<Rc<String>, VarData, FxBuildHasher>,
arg_c: usize,
temp_lb: usize,
arity: usize, // 0 if not at head.
- contents: IndexMap<usize, Rc<String>>,
+ contents: IndexMap<usize, Rc<String>, FxBuildHasher>,
in_use: BTreeSet<usize>,
}
}
}
- fn evacuate_arg<'a, Target>(&mut self, chunk_num: usize, target: &mut Vec<Target>)
+ fn evacuate_arg<'a, Target>(&mut self, chunk_num: usize, target: &mut Vec<Instruction>)
where
Target: CompilationTarget<'a>,
{
var: &String,
lvl: Level,
term_loc: GenContext,
- target: &mut Vec<Target>,
+ target: &mut Vec<Instruction>,
) -> usize
where
Target: CompilationTarget<'a>,
match term_loc {
GenContext::Head => {
if let Level::Shallow = lvl {
- self.evacuate_arg(0, target);
+ self.evacuate_arg::<Target>(0, target);
self.alloc_with_cr(var)
} else {
self.alloc_with_ca(var)
GenContext::Mid(_) => self.alloc_with_ca(var),
GenContext::Last(chunk_num) => {
if let Level::Shallow = lvl {
- self.evacuate_arg(chunk_num, target);
+ self.evacuate_arg::<Target>(chunk_num, target);
self.alloc_with_cr(var)
} else {
self.alloc_with_ca(var)
arity: 0,
arg_c: 1,
temp_lb: 1,
- bindings: IndexMap::new(),
- contents: IndexMap::new(),
+ bindings: IndexMap::with_hasher(FxBuildHasher::default()),
+ contents: IndexMap::with_hasher(FxBuildHasher::default()),
in_use: BTreeSet::new(),
}
}
- fn mark_anon_var<Target>(&mut self, lvl: Level, term_loc: GenContext, target: &mut Vec<Target>)
+ fn mark_anon_var<Target>(
+ &mut self,
+ lvl: Level,
+ term_loc: GenContext,
+ target: &mut Vec<Instruction>,
+ )
where
Target: CompilationTarget<'a>,
{
let k = self.arg_c;
if let GenContext::Last(chunk_num) = term_loc {
- self.evacuate_arg(chunk_num, target);
+ self.evacuate_arg::<Target>(chunk_num, target);
}
self.arg_c += 1;
lvl: Level,
term_loc: GenContext,
cell: &Cell<RegType>,
- target: &mut Vec<Target>,
+ target: &mut Vec<Instruction>,
) where
Target: CompilationTarget<'a>,
{
let k = self.arg_c;
if let GenContext::Last(chunk_num) = term_loc {
- self.evacuate_arg(chunk_num, target);
+ self.evacuate_arg::<Target>(chunk_num, target);
}
self.arg_c += 1;
cell.set(r);
}
- fn mark_var<Target>(
+ fn mark_var<Target: CompilationTarget<'a>>(
&mut self,
var: Rc<String>,
lvl: Level,
cell: &'a Cell<VarReg>,
term_loc: GenContext,
- target: &mut Vec<Target>,
- ) where
- Target: CompilationTarget<'a>,
- {
+ target: &mut Vec<Instruction>,
+ ) {
let (r, is_new_var) = match self.get(var.clone()) {
RegType::Temp(0) => {
// here, r is temporary *and* unassigned.
- let o = self.alloc_reg_to_var(&var, lvl, term_loc, target);
+ let o = self.alloc_reg_to_var::<Target>(&var, lvl, term_loc, target);
cell.set(VarReg::Norm(RegType::Temp(o)));
(RegType::Temp(o), true)
r => (r, false),
};
- self.mark_reserved_var(var, lvl, cell, term_loc, target, r, is_new_var);
+ self.mark_reserved_var::<Target>(var, lvl, cell, term_loc, target, r, is_new_var);
}
- fn mark_reserved_var<Target>(
+ fn mark_reserved_var<Target: CompilationTarget<'a>>(
&mut self,
var: Rc<String>,
lvl: Level,
cell: &'a Cell<VarReg>,
term_loc: GenContext,
- target: &mut Vec<Target>,
+ target: &mut Vec<Instruction>,
r: RegType,
is_new_var: bool,
- ) where
- Target: CompilationTarget<'a>,
- {
+ ) {
match lvl {
Level::Root | Level::Shallow => {
let k = self.arg_c;
if self.is_curr_arg_distinct_from(&var) {
- self.evacuate_arg(term_loc.chunk_num(), target);
+ self.evacuate_arg::<Target>(term_loc.chunk_num(), target);
}
self.arg_c += 1;
}
}
- pub(crate) fn mark_safe_vars(&mut self, query_instr: &QueryInstruction) -> bool {
+ pub(crate) fn mark_safe_vars(&mut self, query_instr: &Instruction) -> bool {
match query_instr {
- &QueryInstruction::PutVariable(r @ RegType::Temp(_), _)
- | &QueryInstruction::SetVariable(r) => {
+ &Instruction::PutVariable(r @ RegType::Temp(_), _) |
+ &Instruction::SetVariable(r) => {
self.safe_vars.insert(r);
true
}
}
}
- pub(crate) fn mark_phase(&mut self, query_instr: &QueryInstruction, phase: usize) {
+ pub(crate) fn mark_phase(&mut self, query_instr: &Instruction, phase: usize) {
match query_instr {
- &QueryInstruction::PutValue(r @ RegType::Perm(_), _)
- | &QueryInstruction::SetValue(r) => {
+ &Instruction::PutValue(r @ RegType::Perm(_), _) |
+ &Instruction::SetValue(r) => {
let p = self.unsafe_vars.entry(r).or_insert(0);
*p = phase;
}
}
}
- pub(crate) fn mark_unsafe_vars(&mut self, query_instr: &mut QueryInstruction, phase: usize) {
+ pub(crate) fn mark_unsafe_vars(&mut self, query_instr: &mut Instruction, phase: usize) {
match query_instr {
- &mut QueryInstruction::PutValue(RegType::Perm(i), arg) => {
+ &mut Instruction::PutValue(RegType::Perm(i), arg) => {
if let Some(p) = self.unsafe_vars.swap_remove(&RegType::Perm(i)) {
if p == phase {
- *query_instr = QueryInstruction::PutUnsafeValue(i, arg);
+ *query_instr = Instruction::PutUnsafeValue(i, arg);
self.safe_vars.insert(RegType::Perm(i));
} else {
self.unsafe_vars.insert(RegType::Perm(i), p);
}
}
}
- &mut QueryInstruction::SetValue(r) => {
+ &mut Instruction::SetValue(r) => {
if !self.safe_vars.contains(&r) {
- *query_instr = QueryInstruction::SetLocalValue(r);
+ *query_instr = Instruction::SetLocalValue(r);
self.safe_vars.insert(r);
self.unsafe_vars.remove(&r);
use crate::arena::*;
use crate::atom_table::*;
-use crate::parser::ast::*;
-use crate::parser::parser::CompositeOpDesc;
-use crate::parser::rug::{Integer, Rational};
-use crate::{is_infix, is_postfix};
-
-use crate::clause_types::*;
+use crate::instructions::*;
use crate::machine::heap::*;
use crate::machine::loader::PredicateQueue;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
+use crate::parser::ast::*;
+use crate::parser::parser::CompositeOpDesc;
+use crate::parser::rug::{Integer, Rational};
use crate::types::*;
+use fxhash::FxBuildHasher;
+
use indexmap::{IndexMap, IndexSet};
use ordered_float::OrderedFloat;
use std::cell::Cell;
use std::convert::TryFrom;
+use std::fmt;
use std::ops::AddAssign;
use std::path::PathBuf;
use std::rc::Rc;
+use crate::{is_infix, is_postfix};
+
pub type PredicateKey = (Atom, usize); // name, arity.
pub type Predicate = Vec<PredicateClause>;
}
}
-//TODO: try to rid yourself and the earth of the next two functions.
pub(crate) fn fetch_atom_op_spec(
name: Atom,
spec: Option<OpDesc>,
}
}
-pub(crate) type ModuleDir = IndexMap<Atom, Module>;
+pub(crate) type ModuleDir = IndexMap<Atom, Module, FxBuildHasher>;
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub enum ModuleExport {
) -> Self {
Module {
module_decl,
- code_dir: CodeDir::new(),
+ code_dir: CodeDir::with_hasher(FxBuildHasher::default()),
op_dir: default_op_dir(),
- meta_predicates: MetaPredicateDir::new(),
- extensible_predicates: ExtensiblePredicates::new(),
- local_extensible_predicates: LocalExtensiblePredicates::new(),
+ meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()),
+ extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()),
+ local_extensible_predicates: LocalExtensiblePredicates::with_hasher(
+ FxBuildHasher::default(),
+ ),
listing_src,
}
}
pub(crate) fn new_in_situ(module_decl: ModuleDecl) -> Self {
Module {
module_decl,
- code_dir: CodeDir::new(),
- op_dir: OpDir::new(),
- meta_predicates: MetaPredicateDir::new(),
- extensible_predicates: ExtensiblePredicates::new(),
- local_extensible_predicates: LocalExtensiblePredicates::new(),
+ code_dir: CodeDir::with_hasher(FxBuildHasher::default()),
+ op_dir: OpDir::with_hasher(FxBuildHasher::default()),
+ meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()),
+ extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()),
+ local_extensible_predicates: LocalExtensiblePredicates::with_hasher(
+ FxBuildHasher::default()
+ ),
listing_src: ListingSource::DynamicallyGenerated,
}
}
}
impl Default for Number {
- #[inline]
fn default() -> Self {
Number::Fixnum(Fixnum::build_with(0))
}
}
+impl fmt::Display for Number {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Number::Float(fl) => write!(f, "{}", fl),
+ Number::Integer(n) => write!(f, "{}", n),
+ Number::Rational(r) => write!(f, "{}", r),
+ Number::Fixnum(n) => write!(f, "{}", n.get_num()),
+ }
+ }
+}
+
pub trait ArenaFrom<T> {
fn arena_from(value: T, arena: &mut Arena) -> Self;
}
}
}
}
-
-#[derive(Debug, Clone, Copy)]
-pub(crate) enum IndexingCodePtr {
- External(usize), // the index points past the indexing instruction prelude.
- DynamicExternal(usize), // an External index of a dynamic predicate, potentially invalidated by retraction.
- Fail,
- Internal(usize), // the index points into the indexing instruction prelude.
-}
-
use crate::arena::*;
use crate::atom_table::*;
+use crate::instructions::*;
use crate::parser::ast::*;
use crate::parser::rug::{Integer, Rational};
use crate::{
sign_char, single_quote_char, small_letter_char, solo_char, variable_indicator_char,
};
-use crate::clause_types::*;
use crate::forms::*;
use crate::heap_iter::*;
use crate::machine::heap::*;
+++ /dev/null
-use crate::arena::*;
-use crate::atom_table::*;
-use crate::parser::ast::*;
-
-use crate::clause_types::*;
-use crate::forms::*;
-use crate::types::*;
-use crate::machine::heap::*;
-use crate::machine::machine_errors::MachineStub;
-
-use indexmap::IndexMap;
-use slice_deque::SliceDeque;
-
-fn reg_type_into_functor(r: RegType) -> MachineStub {
- match r {
- RegType::Temp(r) => functor!(atom!("x"), [fixnum(r)]),
- RegType::Perm(r) => functor!(atom!("y"), [fixnum(r)]),
- }
-}
-
-impl Level {
- fn into_functor(self) -> MachineStub {
- match self {
- Level::Root => functor!(atom!("level"), [atom(atom!("root"))]),
- Level::Shallow => functor!(atom!("level"), [atom(atom!("shallow"))]),
- Level::Deep => functor!(atom!("level"), [atom(atom!("deep"))]),
- }
- }
-}
-
-impl ArithmeticTerm {
- fn into_functor(&self, arena: &mut Arena) -> MachineStub {
- match self {
- &ArithmeticTerm::Reg(r) => reg_type_into_functor(r),
- &ArithmeticTerm::Interm(i) => {
- functor!(atom!("intermediate"), [fixnum(i)])
- }
- &ArithmeticTerm::Number(n) => {
- vec![HeapCellValue::from((n, arena))]
- }
- }
- }
-}
-
-#[derive(Debug, Clone, Copy)]
-pub(crate) enum NextOrFail {
- Next(usize),
- Fail(usize),
-}
-
-impl NextOrFail {
- #[inline]
- pub fn is_next(&self) -> bool {
- if let NextOrFail::Next(_) = self {
- true
- } else {
- false
- }
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub(crate) enum Death {
- Finite(usize),
- Infinity,
-}
-
-#[derive(Debug)]
-pub(crate) enum ChoiceInstruction {
- DynamicElse(usize, Death, NextOrFail),
- DynamicInternalElse(usize, Death, NextOrFail),
- DefaultRetryMeElse(usize),
- DefaultTrustMe(usize),
- RetryMeElse(usize),
- TrustMe(usize),
- TryMeElse(usize),
-}
-
-impl ChoiceInstruction {
- pub(crate) fn to_functor(&self, h: usize) -> MachineStub {
- match self {
- &ChoiceInstruction::DynamicElse(birth, death, next_or_fail) => {
- match (death, next_or_fail) {
- (Death::Infinity, NextOrFail::Next(i)) => {
- functor!(
- atom!("dynamic_else"),
- [fixnum(birth), atom(atom!("inf")), fixnum(i)]
- )
- }
- (Death::Infinity, NextOrFail::Fail(i)) => {
- let next_functor = functor!(atom!("fail"), [fixnum(i)]);
-
- functor!(
- atom!("dynamic_else"),
- [fixnum(birth), atom(atom!("inf")), str(h, 0)],
- [next_functor]
- )
- }
- (Death::Finite(d), NextOrFail::Fail(i)) => {
- let next_functor = functor!(atom!("fail"), [fixnum(i)]);
-
- functor!(
- atom!("dynamic_else"),
- [fixnum(birth), fixnum(d), str(h, 0)],
- [next_functor]
- )
- }
- (Death::Finite(d), NextOrFail::Next(i)) => {
- functor!(atom!("dynamic_else"), [fixnum(birth), fixnum(d), fixnum(i)])
- }
- }
- }
- &ChoiceInstruction::DynamicInternalElse(birth, death, next_or_fail) => {
- match (death, next_or_fail) {
- (Death::Infinity, NextOrFail::Next(i)) => {
- functor!(
- atom!("dynamic_internal_else"),
- [fixnum(birth), atom(atom!("inf")), fixnum(i)]
- )
- }
- (Death::Infinity, NextOrFail::Fail(i)) => {
- let next_functor = functor!(atom!("fail"), [fixnum(i)]);
-
- functor!(
- atom!("dynamic_internal_else"),
- [fixnum(birth), atom(atom!("inf")), str(h, 0)],
- [next_functor]
- )
- }
- (Death::Finite(d), NextOrFail::Fail(i)) => {
- let next_functor = functor!(atom!("fail"), [fixnum(i)]);
-
- functor!(
- atom!("dynamic_internal_else"),
- [fixnum(birth), fixnum(d), str(h, 0)],
- [next_functor]
- )
- }
- (Death::Finite(d), NextOrFail::Next(i)) => {
- functor!(
- atom!("dynamic_internal_else"),
- [fixnum(birth), fixnum(d), fixnum(i)]
- )
- }
- }
- }
- &ChoiceInstruction::TryMeElse(offset) => {
- functor!(atom!("try_me_else"), [fixnum(offset)])
- }
- &ChoiceInstruction::RetryMeElse(offset) => {
- functor!(atom!("retry_me_else"), [fixnum(offset)])
- }
- &ChoiceInstruction::TrustMe(offset) => {
- functor!(atom!("trust_me"), [fixnum(offset)])
- }
- &ChoiceInstruction::DefaultRetryMeElse(offset) => {
- functor!(atom!("default_retry_me_else"), [fixnum(offset)])
- }
- &ChoiceInstruction::DefaultTrustMe(offset) => {
- functor!(atom!("default_trust_me"), [fixnum(offset)])
- }
- }
- }
-}
-
-#[derive(Debug)]
-pub(crate) enum CutInstruction {
- Cut(RegType),
- GetLevel(RegType),
- GetLevelAndUnify(RegType),
- NeckCut,
-}
-
-impl CutInstruction {
- pub(crate) fn to_functor(&self, h: usize) -> MachineStub {
- match self {
- &CutInstruction::Cut(r) => {
- let rt_stub = reg_type_into_functor(r);
- functor!(atom!("cut"), [str(h, 0)], [rt_stub])
- }
- &CutInstruction::GetLevel(r) => {
- let rt_stub = reg_type_into_functor(r);
- functor!(atom!("get_level"), [str(h, 0)], [rt_stub])
- }
- &CutInstruction::GetLevelAndUnify(r) => {
- let rt_stub = reg_type_into_functor(r);
- functor!(atom!("get_level_and_unify"), [str(h, 0)], [rt_stub])
- }
- &CutInstruction::NeckCut => {
- functor!(atom!("neck_cut"))
- }
- }
- }
-}
-
-#[derive(Clone, Copy, Debug)]
-pub(crate) enum IndexedChoiceInstruction {
- Retry(usize),
- Trust(usize),
- Try(usize),
-}
-
-impl IndexedChoiceInstruction {
- pub(crate) fn offset(&self) -> usize {
- match self {
- &IndexedChoiceInstruction::Retry(offset) => offset,
- &IndexedChoiceInstruction::Trust(offset) => offset,
- &IndexedChoiceInstruction::Try(offset) => offset,
- }
- }
-
- pub(crate) fn to_functor(&self) -> MachineStub {
- match self {
- &IndexedChoiceInstruction::Try(offset) => {
- functor!(atom!("try"), [fixnum(offset)])
- }
- &IndexedChoiceInstruction::Trust(offset) => {
- functor!(atom!("trust"), [fixnum(offset)])
- }
- &IndexedChoiceInstruction::Retry(offset) => {
- functor!(atom!("retry"), [fixnum(offset)])
- }
- }
- }
-}
-
-/// A `Line` is an instruction (cf. page 98 of wambook).
-#[derive(Debug)]
-pub(crate) enum IndexingLine {
- Indexing(IndexingInstruction),
- IndexedChoice(SliceDeque<IndexedChoiceInstruction>),
- DynamicIndexedChoice(SliceDeque<usize>),
-}
-
-impl From<IndexingInstruction> for IndexingLine {
- #[inline]
- fn from(instr: IndexingInstruction) -> Self {
- IndexingLine::Indexing(instr)
- }
-}
-
-impl From<SliceDeque<IndexedChoiceInstruction>> for IndexingLine {
- #[inline]
- fn from(instrs: SliceDeque<IndexedChoiceInstruction>) -> Self {
- IndexingLine::IndexedChoice(instrs)
- }
-}
-
-#[derive(Debug)]
-pub(crate) enum Line {
- Arithmetic(ArithmeticInstruction),
- Choice(ChoiceInstruction),
- Control(ControlInstruction),
- Cut(CutInstruction),
- Fact(FactInstruction),
- IndexingCode(Vec<IndexingLine>),
- IndexedChoice(IndexedChoiceInstruction),
- DynamicIndexedChoice(usize),
- Query(QueryInstruction),
-}
-
-impl Line {
- #[inline]
- pub(crate) fn is_head_instr(&self) -> bool {
- match self {
- &Line::Fact(_) => true,
- &Line::Query(_) => true,
- _ => false,
- }
- }
-
- pub(crate) fn enqueue_functors(
- &self,
- mut h: usize,
- arena: &mut Arena,
- functors: &mut Vec<MachineStub>,
- ) {
- match self {
- &Line::Arithmetic(ref arith_instr) => {
- functors.push(arith_instr.to_functor(h, arena))
- }
- &Line::Choice(ref choice_instr) => functors.push(choice_instr.to_functor(h)),
- &Line::Control(ref control_instr) => functors.push(control_instr.to_functor()),
- &Line::Cut(ref cut_instr) => functors.push(cut_instr.to_functor(h)),
- &Line::Fact(ref fact_instr) => functors.push(fact_instr.to_functor(h)),
- &Line::IndexingCode(ref indexing_instrs) => {
- for indexing_instr in indexing_instrs {
- match indexing_instr {
- IndexingLine::Indexing(indexing_instr) => {
- let section = indexing_instr.to_functor(h);
- h += section.len();
- functors.push(section);
- }
- IndexingLine::IndexedChoice(indexed_choice_instrs) => {
- for indexed_choice_instr in indexed_choice_instrs {
- let section = indexed_choice_instr.to_functor();
- h += section.len();
- functors.push(section);
- }
- }
- IndexingLine::DynamicIndexedChoice(indexed_choice_instrs) => {
- for indexed_choice_instr in indexed_choice_instrs {
- let section = functor!(
- atom!("dynamic"),
- [fixnum(*indexed_choice_instr)]
- );
-
- h += section.len();
- functors.push(section);
- }
- }
- }
- }
- }
- &Line::IndexedChoice(ref indexed_choice_instr) => {
- functors.push(indexed_choice_instr.to_functor())
- }
- &Line::DynamicIndexedChoice(ref indexed_choice_instr) => {
- functors.push(functor!(atom!("dynamic"), [fixnum(*indexed_choice_instr)]));
- }
- &Line::Query(ref query_instr) => functors.push(query_instr.to_functor(h)),
- }
- }
-}
-
-#[inline]
-pub(crate) fn to_indexing_line_mut(line: &mut Line) -> Option<&mut Vec<IndexingLine>> {
- match line {
- Line::IndexingCode(ref mut indexing_code) => Some(indexing_code),
- _ => None,
- }
-}
-
-#[inline]
-pub(crate) fn to_indexing_line(line: &Line) -> Option<&Vec<IndexingLine>> {
- match line {
- Line::IndexingCode(ref indexing_code) => Some(indexing_code),
- _ => None,
- }
-}
-
-#[derive(Debug, Copy, Clone)]
-pub enum ArithmeticInstruction {
- Add(ArithmeticTerm, ArithmeticTerm, usize),
- Sub(ArithmeticTerm, ArithmeticTerm, usize),
- Mul(ArithmeticTerm, ArithmeticTerm, usize),
- Pow(ArithmeticTerm, ArithmeticTerm, usize),
- IntPow(ArithmeticTerm, ArithmeticTerm, usize),
- IDiv(ArithmeticTerm, ArithmeticTerm, usize),
- Max(ArithmeticTerm, ArithmeticTerm, usize),
- Min(ArithmeticTerm, ArithmeticTerm, usize),
- IntFloorDiv(ArithmeticTerm, ArithmeticTerm, usize),
- RDiv(ArithmeticTerm, ArithmeticTerm, usize),
- Div(ArithmeticTerm, ArithmeticTerm, usize),
- Shl(ArithmeticTerm, ArithmeticTerm, usize),
- Shr(ArithmeticTerm, ArithmeticTerm, usize),
- Xor(ArithmeticTerm, ArithmeticTerm, usize),
- And(ArithmeticTerm, ArithmeticTerm, usize),
- Or(ArithmeticTerm, ArithmeticTerm, usize),
- Mod(ArithmeticTerm, ArithmeticTerm, usize),
- Rem(ArithmeticTerm, ArithmeticTerm, usize),
- Gcd(ArithmeticTerm, ArithmeticTerm, usize),
- Sign(ArithmeticTerm, usize),
- Cos(ArithmeticTerm, usize),
- Sin(ArithmeticTerm, usize),
- Tan(ArithmeticTerm, usize),
- Log(ArithmeticTerm, usize),
- Exp(ArithmeticTerm, usize),
- ACos(ArithmeticTerm, usize),
- ASin(ArithmeticTerm, usize),
- ATan(ArithmeticTerm, usize),
- ATan2(ArithmeticTerm, ArithmeticTerm, usize),
- Sqrt(ArithmeticTerm, usize),
- Abs(ArithmeticTerm, usize),
- Float(ArithmeticTerm, usize),
- Truncate(ArithmeticTerm, usize),
- Round(ArithmeticTerm, usize),
- Ceiling(ArithmeticTerm, usize),
- Floor(ArithmeticTerm, usize),
- Neg(ArithmeticTerm, usize),
- Plus(ArithmeticTerm, usize),
- BitwiseComplement(ArithmeticTerm, usize),
-}
-
-fn arith_instr_unary_functor(
- h: usize,
- name: Atom,
- arena: &mut Arena,
- at: &ArithmeticTerm,
- t: usize,
-) -> MachineStub {
- let at_stub = at.into_functor(arena);
- functor!(name, [str(h, 0), fixnum(t)], [at_stub])
-}
-
-fn arith_instr_bin_functor(
- h: usize,
- name: Atom,
- arena: &mut Arena,
- at_1: &ArithmeticTerm,
- at_2: &ArithmeticTerm,
- t: usize,
-) -> MachineStub {
- let at_1_stub = at_1.into_functor(arena);
- let at_2_stub = at_2.into_functor(arena);
-
- functor!(
- name,
- [str(h, 0), str(h, 1), fixnum(t)],
- [at_1_stub, at_2_stub]
- )
-}
-
-impl ArithmeticInstruction {
- pub(crate) fn to_functor(
- &self,
- h: usize,
- arena: &mut Arena,
- ) -> MachineStub {
- match self {
- &ArithmeticInstruction::Add(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("add"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Sub(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("sub"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Mul(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("mul"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::IntPow(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("int_pow"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Pow(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("pow"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::IDiv(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("idiv"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Max(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("max"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Min(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("min"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::IntFloorDiv(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("int_floor_div"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::RDiv(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("rdiv"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Div(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("div"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Shl(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("shl"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Shr(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("shr"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Xor(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("xor"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::And(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("and"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Or(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("or"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Mod(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("mod"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Rem(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("rem"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::ATan2(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("rem"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Gcd(ref at_1, ref at_2, t) => {
- arith_instr_bin_functor(h, atom!("gcd"), arena, at_1, at_2, t)
- }
- &ArithmeticInstruction::Sign(ref at, t) => {
- arith_instr_unary_functor(h, atom!("sign"), arena, at, t)
- }
- &ArithmeticInstruction::Cos(ref at, t) => {
- arith_instr_unary_functor(h, atom!("cos"), arena, at, t)
- }
- &ArithmeticInstruction::Sin(ref at, t) => {
- arith_instr_unary_functor(h, atom!("sin"), arena, at, t)
- }
- &ArithmeticInstruction::Tan(ref at, t) => {
- arith_instr_unary_functor(h, atom!("tan"), arena, at, t)
- }
- &ArithmeticInstruction::Log(ref at, t) => {
- arith_instr_unary_functor(h, atom!("log"), arena, at, t)
- }
- &ArithmeticInstruction::Exp(ref at, t) => {
- arith_instr_unary_functor(h, atom!("exp"), arena, at, t)
- }
- &ArithmeticInstruction::ACos(ref at, t) => {
- arith_instr_unary_functor(h, atom!("acos"), arena, at, t)
- }
- &ArithmeticInstruction::ASin(ref at, t) => {
- arith_instr_unary_functor(h, atom!("asin"), arena, at, t)
- }
- &ArithmeticInstruction::ATan(ref at, t) => {
- arith_instr_unary_functor(h, atom!("atan"), arena, at, t)
- }
- &ArithmeticInstruction::Sqrt(ref at, t) => {
- arith_instr_unary_functor(h, atom!("sqrt"), arena, at, t)
- }
- &ArithmeticInstruction::Abs(ref at, t) => {
- arith_instr_unary_functor(h, atom!("abs"), arena, at, t)
- }
- &ArithmeticInstruction::Float(ref at, t) => {
- arith_instr_unary_functor(h, atom!("float"), arena, at, t)
- }
- &ArithmeticInstruction::Truncate(ref at, t) => {
- arith_instr_unary_functor(h, atom!("truncate"), arena, at, t)
- }
- &ArithmeticInstruction::Round(ref at, t) => {
- arith_instr_unary_functor(h, atom!("round"), arena, at, t)
- }
- &ArithmeticInstruction::Ceiling(ref at, t) => {
- arith_instr_unary_functor(h, atom!("ceiling"), arena, at, t)
- }
- &ArithmeticInstruction::Floor(ref at, t) => {
- arith_instr_unary_functor(h, atom!("floor"), arena, at, t)
- }
- &ArithmeticInstruction::Neg(ref at, t) => arith_instr_unary_functor(
- h,
- atom!("-"),
- arena,
- at,
- t,
- ),
- &ArithmeticInstruction::Plus(ref at, t) => arith_instr_unary_functor(
- h,
- atom!("+"),
- arena,
- at,
- t,
- ),
- &ArithmeticInstruction::BitwiseComplement(ref at, t) => arith_instr_unary_functor(
- h,
- atom!("\\"),
- arena,
- at,
- t,
- ),
- }
- }
-}
-
-#[derive(Debug)]
-pub enum ControlInstruction {
- Allocate(usize), // num_frames.
- // name, arity, perm_vars after threshold, last call, use default call policy.
- CallClause(ClauseType, usize, usize, bool, bool),
- Deallocate,
- JmpBy(usize, usize, usize, bool), // arity, global_offset, perm_vars after threshold, last call.
- RevJmpBy(usize), // notice the lack of context change as in
- // JmpBy. RevJmpBy is used only to patch extensible
- // predicates together.
- Proceed,
-}
-
-impl ControlInstruction {
- pub(crate) fn perm_vars(&self) -> Option<usize> {
- match self {
- ControlInstruction::CallClause(_, _, num_cells, ..) => Some(*num_cells),
- ControlInstruction::JmpBy(_, _, num_cells, ..) => Some(*num_cells),
- _ => None,
- }
- }
-
- pub(crate) fn to_functor(&self) -> MachineStub {
- match self {
- &ControlInstruction::Allocate(num_frames) => {
- functor!(atom!("allocate"), [fixnum(num_frames)])
- }
- &ControlInstruction::CallClause(ref ct, arity, _, false, _) => {
- functor!(atom!("call"), [atom(ct.name()), fixnum(arity)])
- }
- &ControlInstruction::CallClause(ref ct, arity, _, true, _) => {
- functor!(atom!("execute"), [atom(ct.name()), fixnum(arity)])
- }
- &ControlInstruction::Deallocate => {
- functor!(atom!("deallocate"))
- }
- &ControlInstruction::JmpBy(_, offset, ..) => {
- functor!(atom!("jmp_by"), [fixnum(offset)])
- }
- &ControlInstruction::RevJmpBy(offset) => {
- functor!(atom!("rev_jmp_by"), [fixnum(offset)])
- }
- &ControlInstruction::Proceed => {
- functor!(atom!("proceed"))
- }
- }
- }
-}
-
-/// `IndexingInstruction` cf. page 110 of wambook.
-#[derive(Debug)]
-pub(crate) enum IndexingInstruction {
- // The first index is the optimal argument being indexed.
- SwitchOnTerm(
- usize,
- IndexingCodePtr,
- IndexingCodePtr,
- IndexingCodePtr,
- IndexingCodePtr,
- ),
- SwitchOnConstant(IndexMap<Literal, IndexingCodePtr>),
- SwitchOnStructure(IndexMap<(Atom, usize), IndexingCodePtr>),
-}
-
-impl IndexingCodePtr {
- #[allow(dead_code)]
- pub(crate) fn to_functor(self) -> MachineStub {
- match self {
- IndexingCodePtr::DynamicExternal(o) => functor!(atom!("dynamic_external"), [fixnum(o)]),
- IndexingCodePtr::External(o) => functor!(atom!("external"), [fixnum(o)]),
- IndexingCodePtr::Internal(o) => functor!(atom!("internal"), [fixnum(o)]),
- IndexingCodePtr::Fail => {
- vec![atom_as_cell!(atom!("fail"))]
- },
- }
- }
-}
-
-impl IndexingInstruction {
- pub(crate) fn to_functor(&self, mut h: usize) -> MachineStub {
- match self {
- &IndexingInstruction::SwitchOnTerm(arg, vars, constants, lists, structures) => {
- functor!(
- atom!("switch_on_term"),
- [
- fixnum(arg),
- indexing_code_ptr(h, vars),
- indexing_code_ptr(h, constants),
- indexing_code_ptr(h, lists),
- indexing_code_ptr(h, structures)
- ]
- )
- }
- &IndexingInstruction::SwitchOnConstant(ref constants) => {
- let mut key_value_list_stub = vec![];
- let orig_h = h;
-
- h += 2; // skip the 2-cell "switch_on_constant" functor.
-
- for (c, ptr) in constants.iter() {
- let key_value_pair = functor!(
- atom!(":"),
- [literal(*c), indexing_code_ptr(h + 3, *ptr)]
- );
-
- key_value_list_stub.push(list_loc_as_cell!(h + 1));
- key_value_list_stub.push(str_loc_as_cell!(h + 3));
- key_value_list_stub.push(heap_loc_as_cell!(h + 3 + key_value_pair.len()));
-
- h += key_value_pair.len() + 3;
- key_value_list_stub.extend(key_value_pair.into_iter());
- }
-
- key_value_list_stub.push(empty_list_as_cell!());
-
- functor!(
- atom!("switch_on_constant"),
- [str(orig_h, 0)],
- [key_value_list_stub]
- )
- }
- &IndexingInstruction::SwitchOnStructure(ref structures) => {
- let mut key_value_list_stub = vec![];
- let orig_h = h;
-
- h += 2; // skip the 2-cell "switch_on_constant" functor.
-
- for ((name, arity), ptr) in structures.iter() {
- let predicate_indicator_stub = functor!(
- atom!("/"),
- [atom(name), fixnum(*arity)]
- );
-
- let key_value_pair = functor!(
- atom!(":"),
- [str(h + 3, 0), indexing_code_ptr(h + 3, *ptr)],
- [predicate_indicator_stub]
- );
-
- key_value_list_stub.push(list_loc_as_cell!(h + 1));
- key_value_list_stub.push(str_loc_as_cell!(h + 3));
- key_value_list_stub.push(heap_loc_as_cell!(h + 3 + key_value_pair.len()));
-
- h += key_value_pair.len() + 3;
- key_value_list_stub.extend(key_value_pair.into_iter());
- }
-
- key_value_list_stub.push(empty_list_as_cell!());
-
- functor!(
- atom!("switch_on_structure"),
- [str(orig_h, 0)],
- [key_value_list_stub]
- )
- }
- }
- }
-}
-
-#[derive(Debug, Clone)]
-pub enum FactInstruction {
- GetConstant(Level, HeapCellValue, RegType),
- GetList(Level, RegType),
- GetPartialString(Level, Atom, RegType, bool),
- GetStructure(ClauseType, usize, RegType),
- GetValue(RegType, usize),
- GetVariable(RegType, usize),
- UnifyConstant(HeapCellValue),
- UnifyLocalValue(RegType),
- UnifyVariable(RegType),
- UnifyValue(RegType),
- UnifyVoid(usize),
-}
-
-impl FactInstruction {
- pub(crate) fn to_functor(&self, h: usize) -> MachineStub {
- match self {
- &FactInstruction::GetConstant(lvl, c, r) => {
- let lvl_stub = lvl.into_functor();
- let rt_stub = reg_type_into_functor(r);
-
- functor!(
- atom!("get_constant"),
- [str(h, 0), cell(c), str(h, 1)],
- [lvl_stub, rt_stub]
- )
- }
- &FactInstruction::GetList(lvl, r) => {
- let lvl_stub = lvl.into_functor();
- let rt_stub = reg_type_into_functor(r);
-
- functor!(
- atom!("get_list"),
- [str(h, 0), str(h, 1)],
- [lvl_stub, rt_stub]
- )
- }
- &FactInstruction::GetPartialString(lvl, s, r, has_tail) => {
- let lvl_stub = lvl.into_functor();
- let rt_stub = reg_type_into_functor(r);
-
- functor!(
- atom!("get_partial_string"),
- [
- str(h, 0),
- string(h, s),
- str(h, 1),
- boolean(has_tail)
- ],
- [lvl_stub, rt_stub]
- )
- }
- &FactInstruction::GetStructure(ref ct, arity, r) => {
- let rt_stub = reg_type_into_functor(r);
-
- functor!(
- atom!("get_structure"),
- [atom(ct.name()), fixnum(arity), str(h, 0)],
- [rt_stub]
- )
- }
- &FactInstruction::GetValue(r, arg) => {
- let rt_stub = reg_type_into_functor(r);
-
- functor!(atom!("get_value"), [str(h, 0), fixnum(arg)], [rt_stub])
- }
- &FactInstruction::GetVariable(r, arg) => {
- let rt_stub = reg_type_into_functor(r);
-
- functor!(atom!("get_variable"), [str(h, 0), fixnum(arg)], [rt_stub])
- }
- &FactInstruction::UnifyConstant(c) => {
- functor!(atom!("unify_constant"), [cell(c)])
- }
- &FactInstruction::UnifyLocalValue(r) => {
- let rt_stub = reg_type_into_functor(r);
-
- functor!(atom!("unify_local_value"), [str(h, 0)], [rt_stub])
- }
- &FactInstruction::UnifyVariable(r) => {
- let rt_stub = reg_type_into_functor(r);
-
- functor!(atom!("unify_variable"), [str(h, 0)], [rt_stub])
- }
- &FactInstruction::UnifyValue(r) => {
- let rt_stub = reg_type_into_functor(r);
-
- functor!(atom!("unify_value"), [str(h, 0)], [rt_stub])
- }
- &FactInstruction::UnifyVoid(vars) => {
- functor!(atom!("unify_void"), [fixnum(vars)])
- }
- }
- }
-}
-
-#[derive(Debug, Clone)]
-pub(crate) enum QueryInstruction {
- GetVariable(RegType, usize),
- PutConstant(Level, HeapCellValue, RegType),
- PutList(Level, RegType),
- PutPartialString(Level, Atom, RegType, bool),
- PutStructure(ClauseType, usize, RegType),
- PutUnsafeValue(usize, usize),
- PutValue(RegType, usize),
- PutVariable(RegType, usize),
- SetConstant(HeapCellValue),
- SetLocalValue(RegType),
- SetVariable(RegType),
- SetValue(RegType),
- SetVoid(usize),
-}
-
-impl QueryInstruction {
- pub(crate) fn to_functor(&self, h: usize) -> MachineStub {
- match self {
- &QueryInstruction::PutUnsafeValue(norm, arg) => {
- functor!(atom!("put_unsafe_value"), [fixnum(norm), fixnum(arg)])
- }
- &QueryInstruction::PutConstant(lvl, c, r) => {
- let lvl_stub = lvl.into_functor();
- let rt_stub = reg_type_into_functor(r);
-
- functor!(
- atom!("put_constant"),
- [str(h, 0), cell(c), str(h, 1)],
- [lvl_stub, rt_stub]
- )
- }
- &QueryInstruction::PutList(lvl, r) => {
- let lvl_stub = lvl.into_functor();
- let rt_stub = reg_type_into_functor(r);
-
- functor!(
- atom!("put_list"),
- [str(h, 0), str(h, 1)],
- [lvl_stub, rt_stub]
- )
- }
- &QueryInstruction::PutPartialString(lvl, s, r, has_tail) => {
- let lvl_stub = lvl.into_functor();
- let rt_stub = reg_type_into_functor(r);
-
- functor!(
- atom!("put_partial_string"),
- [
- str(h, 0),
- string(h, s),
- str(h, 1),
- boolean(has_tail)
- ],
- [lvl_stub, rt_stub]
- )
- }
- &QueryInstruction::PutStructure(ref ct, arity, r) => {
- let rt_stub = reg_type_into_functor(r);
-
- functor!(
- atom!("put_structure"),
- [atom(ct.name()), fixnum(arity), str(h, 0)],
- [rt_stub]
- )
- }
- &QueryInstruction::PutValue(r, arg) => {
- let rt_stub = reg_type_into_functor(r);
-
- functor!(atom!("put_value"), [str(h, 0), fixnum(arg)], [rt_stub])
- }
- &QueryInstruction::GetVariable(r, arg) => {
- let rt_stub = reg_type_into_functor(r);
-
- functor!(atom!("get_variable"), [str(h, 0), fixnum(arg)], [rt_stub])
- }
- &QueryInstruction::PutVariable(r, arg) => {
- let rt_stub = reg_type_into_functor(r);
-
- functor!(atom!("put_variable"), [str(h, 0), fixnum(arg)], [rt_stub])
- }
- &QueryInstruction::SetConstant(c) => {
- functor!(atom!("set_constant"), [cell(c)], [])
- }
- &QueryInstruction::SetLocalValue(r) => {
- let rt_stub = reg_type_into_functor(r);
-
- functor!(atom!("set_local_value"), [str(h, 0)], [rt_stub])
- }
- &QueryInstruction::SetVariable(r) => {
- let rt_stub = reg_type_into_functor(r);
-
- functor!(atom!("set_variable"), [str(h, 0)], [rt_stub])
- }
- &QueryInstruction::SetValue(r) => {
- let rt_stub = reg_type_into_functor(r);
-
- functor!(atom!("set_value"), [str(h, 0)], [rt_stub])
- }
- &QueryInstruction::SetVoid(vars) => {
- functor!(atom!("set_void"), [fixnum(vars)])
- }
- }
- }
-}
-
-pub(crate) type CompiledFact = Vec<FactInstruction>;
-
-pub(crate) type Code = Vec<Line>;
use crate::atom_table::*;
-use crate::parser::ast::*;
-
-use crate::clause_types::*;
use crate::forms::*;
+use crate::instructions::*;
use crate::machine::machine_indices::*;
+use crate::parser::ast::*;
use std::cell::Cell;
use std::collections::VecDeque;
match term {
Term::AnonVar => TermIterState::AnonVar(lvl),
Term::Clause(cell, name, subterms) => {
- let ct = ClauseType::Named(name.clone(), subterms.len(), CodeIndex::default());
+ let ct = ClauseType::Named(subterms.len(), *name, CodeIndex::default());
TermIterState::Clause(lvl, 0, cell, ct, subterms)
}
Term::Cons(cell, head, tail) => {
fn new(term: &'a QueryTerm) -> Self {
match term {
- &QueryTerm::Clause(ref cell, ClauseType::CallN, ref terms, _) => {
- let state = TermIterState::Clause(Level::Root, 1, cell, ClauseType::CallN, terms);
+ &QueryTerm::Clause(ref cell, ClauseType::CallN(arity), ref terms, _) => {
+ let state = TermIterState::Clause(Level::Root, 1, cell, ClauseType::CallN(arity), terms);
QueryIterator {
state_stack: vec![state],
}
TermIterState::Clause(lvl, child_num, cell, ct, child_terms) => {
if child_num == child_terms.len() {
match ct {
- ClauseType::CallN => {
+ ClauseType::CallN(_) => {
self.push_subterm(Level::Shallow, &child_terms[0]);
}
ClauseType::Named(..) => {
}
ChunkedTerm::BodyTerm(&QueryTerm::Clause(
_,
- ClauseType::CallN,
+ ClauseType::CallN(_),
ref subterms,
_,
)) => {
+#![recursion_limit = "4112"]
+
#[macro_use]
extern crate static_assertions;
pub mod parser;
mod allocator;
mod arithmetic;
-mod clause_types;
pub mod codegen;
mod debray_allocator;
mod fixtures;
mod heap_iter;
pub mod heap_print;
mod indexing;
-mod instructions;
+#[macro_use]
+pub mod instructions;
mod iterators;
pub mod machine;
mod raw_block;
( nonvar(X) ->
Lower =< X,
X =< Upper
- ; % compare(Ord, Lower, Upper),
- % between_(Ord, Lower, Upper, X)
- Lower =< Upper,
+ ; Lower =< Upper,
between_(Lower, Upper, X)
).
)
).
-/*
-between_(<, Lower0, Upper, X) :-
- ( X = Lower0
- ; Lower1 is Lower0 + 1,
- compare(Ord, Lower1, Upper),
- between_(Ord, Lower1, Upper, X)
- ).
-between_(=, Upper, Upper, Upper).
-*/
-
enumerate_nats(I, I).
enumerate_nats(I0, N) :-
I1 is I0 + 1,
call(G, A, B, C, D, E, F, G, H) :- '$call'(G, A, B, C, D, E, F, G, H).
+% dynamic module resolution.
Module : Predicate :-
( atom(Module) -> '$module_call'(Module, Predicate)
; throw(error(type_error(atom, Module), (:)/2))
).
-
-% dynamic module resolution.
-
:(Module, Predicate, A1) :-
( atom(Module) ->
'$module_call'(A1, Module, Predicate)
!,
'$skip_max_list'(M, -1, Xs, Xs0),
( Xs0 == [] -> N = M
- ; var(Xs0) -> length_addendum(Xs0, N, M)).
+ ; var(Xs0) -> length_addendum(Xs0, N, M)
+ ).
length(Xs, N) :-
integer(N),
- N >= 0, !,
+ N >= 0,
+ !,
'$skip_max_list'(M, N, Xs, Xs0),
( Xs0 == [] -> N = M
- ; var(Xs0) -> R is N-M, length_rundown(Xs0, R)).
+ ; var(Xs0) -> R is N-M, length_rundown(Xs0, R)
+ ).
length(_, N) :-
integer(N), !,
domain_error(not_less_than_zero, N, length/2).
run_initialization_goals(Module) :-
( predicate_property(Module:'$initialization_goals'(_), dynamic) ->
% FIXME: failing here. also, see add_module.
- '$debug_hook',
findall(Module:Goal, '$call'(builtins:retract(Module:'$initialization_goals'(Goal))), Goals),
abolish(Module:'$initialization_goals'/1),
( maplist(Module:call, Goals) ->
check_predicate_property(meta_predicate, Module, Name, Arity, MetaPredicateTerm) :-
- '$cpp_meta_predicate_property'(Module, Name, Arity, MetaPredicateTerm).
+ '$meta_predicate_property'(Module, Name, Arity, MetaPredicateTerm).
check_predicate_property(built_in, _, Name, Arity, built_in) :-
- '$cpp_built_in_property'(Name, Arity).
+ '$built_in_property'(Name, Arity).
check_predicate_property(dynamic, Module, Name, Arity, dynamic) :-
- '$cpp_dynamic_property'(Module, Name, Arity).
+ '$dynamic_property'(Module, Name, Arity).
check_predicate_property(multifile, Module, Name, Arity, multifile) :-
- '$cpp_multifile_property'(Module, Name, Arity).
+ '$multifile_property'(Module, Name, Arity).
check_predicate_property(discontiguous, Module, Name, Arity, discontiguous) :-
- '$cpp_discontiguous_property'(Module, Name, Arity).
+ '$discontiguous_property'(Module, Name, Arity).
use crate::arena::*;
use crate::arithmetic::*;
use crate::atom_table::*;
-use crate::clause_types::*;
use crate::forms::*;
use crate::heap_iter::*;
use crate::machine::machine_errors::*;
pub fn get_number(&mut self, at: &ArithmeticTerm) -> Result<Number, MachineStub> {
match at {
&ArithmeticTerm::Reg(r) => {
- let value = self.store(self.deref(self[r]));
+ let value = self.store(self.deref(self[r]));
match Number::try_from(value) {
Ok(n) => Ok(n),
pub(super) struct AttrVarInitializer {
pub(super) attr_var_queue: Vec<usize>,
pub(super) bindings: Bindings,
- pub(super) cp: LocalCodePtr,
- pub(super) instigating_p: LocalCodePtr,
+ pub(super) p: usize,
+ pub(super) cp: usize,
+ // pub(super) instigating_p: usize,
pub(super) verify_attrs_loc: usize,
}
AttrVarInitializer {
attr_var_queue: vec![],
bindings: vec![],
- instigating_p: LocalCodePtr::default(),
- cp: LocalCodePtr::default(),
+ p: 0,
+ cp: 0,
verify_attrs_loc,
}
}
impl MachineState {
pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: HeapCellValue) {
if self.attr_var_init.bindings.is_empty() {
- self.attr_var_init.instigating_p = self.p.local();
+ // save self.p and self.cp and ensure that the next
+ // instruction is InstallVerifyAttrInterrupt.
- if self.last_call {
- self.attr_var_init.cp = self.cp;
- } else {
- self.attr_var_init.cp = self.p.local() + 1;
- }
+ self.attr_var_init.p = self.p;
+ self.attr_var_init.cp = self.cp;
- self.p = CodePtr::VerifyAttrInterrupt(self.attr_var_init.verify_attrs_loc);
+ self.p = INSTALL_VERIFY_ATTR_INTERRUPT - 1;
+ self.cp = INSTALL_VERIFY_ATTR_INTERRUPT;
}
self.attr_var_init.bindings.push((h, addr));
}
pub(super) fn verify_attr_interrupt(&mut self, p: usize) {
- self.allocate(self.num_of_args + 2);
+ self.allocate(self.num_of_args + 3);
let e = self.e;
- self.stack.index_and_frame_mut(e).prelude.interrupt_cp = self.attr_var_init.cp;
+ let and_frame = self.stack.index_and_frame_mut(e);
for i in 1..self.num_of_args + 1 {
- self.stack.index_and_frame_mut(e)[i] = self[RegType::Temp(i)];
+ and_frame[i] = self.registers[i];
}
- self.stack.index_and_frame_mut(e)[self.num_of_args + 1] =
+ and_frame[self.num_of_args + 1] =
fixnum_as_cell!(Fixnum::build_with(self.b0 as i64));
- self.stack.index_and_frame_mut(e)[self.num_of_args + 2] =
+ and_frame[self.num_of_args + 2] =
fixnum_as_cell!(Fixnum::build_with(self.num_of_args as i64));
+ and_frame[self.num_of_args + 3] =
+ fixnum_as_cell!(Fixnum::build_with(self.attr_var_init.cp as i64));
self.verify_attributes();
- self.num_of_args = 2;
+ self.num_of_args = 3;
self.b0 = self.b;
- self.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
+ self.p = p;
}
pub(super) fn attr_vars_of_term(&mut self, cell: HeapCellValue) -> Vec<HeapCellValue> {
+++ /dev/null
-use crate::clause_types::*;
-use crate::instructions::*;
-use crate::machine::{Machine, MachineState};
-use crate::machine::machine_indices::*;
-
-use std::fmt;
-
-pub(crate) enum OwnedOrIndexed {
- Indexed(usize),
- Owned(Line),
-}
-
-impl fmt::Debug for OwnedOrIndexed {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- &OwnedOrIndexed::Indexed(ref index) => write!(f, "Indexed({:?})", index),
- &OwnedOrIndexed::Owned(ref owned) => write!(f, "Owned({:?})", owned),
- }
- }
-}
-
-impl OwnedOrIndexed {
- #[inline(always)]
- pub(crate) fn as_ref<'a>(&'a self, code: &'a Code) -> &'a Line {
- match self {
- &OwnedOrIndexed::Indexed(p) => &code[p],
- &OwnedOrIndexed::Owned(ref r) => r,
- }
- }
-}
-
-
-// TODO: remove this, replace with just 'Code'.
-#[derive(Debug)]
-pub struct CodeRepo {
- pub(super) code: Code,
-}
-
-impl CodeRepo {
- pub(super) fn lookup_instr(&self, machine_st: &MachineState, p: &CodePtr) -> Option<OwnedOrIndexed> {
- match p {
- &CodePtr::Local(local) => {
- return Some(self.lookup_local_instr(machine_st, local));
- }
- &CodePtr::REPL(..) => None,
- &CodePtr::BuiltInClause(ref built_in, _) => {
- let call_clause = call_clause!(
- ClauseType::BuiltIn(built_in.clone()),
- built_in.arity(),
- 0,
- machine_st.last_call
- );
-
- Some(OwnedOrIndexed::Owned(call_clause))
- }
- &CodePtr::CallN(arity, _, last_call) => {
- let call_clause = call_clause!(ClauseType::CallN, arity, 0, last_call);
- Some(OwnedOrIndexed::Owned(call_clause))
- }
- &CodePtr::VerifyAttrInterrupt(p) => Some(OwnedOrIndexed::Indexed(p)),
- }
- }
-
- #[inline]
- pub(super) fn lookup_local_instr(&self, machine_st: &MachineState, p: LocalCodePtr) -> OwnedOrIndexed {
- match p {
- LocalCodePtr::Halt => {
- // exit with the interrupt exit code.
- std::process::exit(1);
- }
- LocalCodePtr::DirEntry(p) => match &self.code[p] {
- &Line::IndexingCode(ref indexing_lines) => {
- match &indexing_lines[machine_st.oip as usize] {
- &IndexingLine::IndexedChoice(ref indexed_choice_instrs) => {
- OwnedOrIndexed::Owned(
- Line::IndexedChoice(indexed_choice_instrs[machine_st.iip as usize])
- )
- }
- &IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => {
- OwnedOrIndexed::Owned(
- Line::DynamicIndexedChoice(indexed_choice_instrs[machine_st.iip as usize])
- )
- }
- _ => {
- OwnedOrIndexed::Indexed(p)
- }
- }
- }
- _ => OwnedOrIndexed::Indexed(p)
- }
- }
- }
-}
-
-impl Machine {
- pub(super) fn find_living_dynamic_else(&self, mut p: usize) -> Option<(usize, usize)> {
- loop {
- match &self.code_repo.code[p] {
- &Line::Choice(ChoiceInstruction::DynamicElse(
- birth,
- death,
- NextOrFail::Next(i),
- )) => {
- if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
- return Some((p, i));
- } else if i > 0 {
- p += i;
- } else {
- return None;
- }
- }
- &Line::Choice(ChoiceInstruction::DynamicElse(
- birth,
- death,
- NextOrFail::Fail(_),
- )) => {
- if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
- return Some((p, 0));
- } else {
- return None;
- }
- }
- &Line::Choice(ChoiceInstruction::DynamicInternalElse(
- birth,
- death,
- NextOrFail::Next(i),
- )) => {
- if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
- return Some((p, i));
- } else if i > 0 {
- p += i;
- } else {
- return None;
- }
- }
- &Line::Choice(ChoiceInstruction::DynamicInternalElse(
- birth,
- death,
- NextOrFail::Fail(_),
- )) => {
- if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
- return Some((p, 0));
- } else {
- return None;
- }
- }
- &Line::Control(ControlInstruction::RevJmpBy(i)) => {
- p -= i;
- }
- _ => {
- unreachable!();
- }
- }
- }
- }
-
- pub(super) fn find_living_dynamic(&self, oi: u32, mut ii: u32) -> Option<(usize, u32, u32, bool)> {
- let p = self.machine_st.p.local().abs_loc();
-
- let indexed_choice_instrs = match &self.code_repo.code[p] {
- Line::IndexingCode(ref indexing_code) => match &indexing_code[oi as usize] {
- IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => {
- indexed_choice_instrs
- }
- _ => unreachable!(),
- },
- _ => unreachable!(),
- };
-
- loop {
- match &indexed_choice_instrs.get(ii as usize) {
- Some(&offset) => match &self.code_repo.code[p + offset - 1] {
- &Line::Choice(ChoiceInstruction::DynamicInternalElse(
- birth,
- death,
- next_or_fail,
- )) => {
- if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
- return Some((offset, oi, ii, next_or_fail.is_next()));
- } else {
- ii += 1;
- }
- }
- _ => unreachable!(),
- },
- None => return None,
- }
- }
- }
-}
-
-impl CodeRepo {
- #[inline]
- pub(super) fn new() -> Self {
- CodeRepo { code: Code::new() }
- }
-}
use indexmap::IndexSet;
-fn capture_offset(line: &Line, index: usize, stack: &mut Vec<usize>) -> bool {
+fn capture_offset(line: &Instruction, index: usize, stack: &mut Vec<usize>) -> bool {
match line {
- &Line::Choice(ChoiceInstruction::TryMeElse(offset)) if offset > 0 => {
+ &Instruction::TryMeElse(offset) if offset > 0 => {
stack.push(index + offset);
}
- &Line::Choice(ChoiceInstruction::DefaultRetryMeElse(offset))
- | &Line::Choice(ChoiceInstruction::RetryMeElse(offset))
+ &Instruction::DefaultRetryMeElse(offset) |
+ &Instruction::RetryMeElse(offset)
if offset > 0 =>
{
stack.push(index + offset);
}
- &Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(offset)))
+ &Instruction::DynamicElse(_, _, NextOrFail::Next(offset))
if offset > 0 =>
{
stack.push(index + offset);
}
- &Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(offset)))
+ &Instruction::DynamicInternalElse(_, _, NextOrFail::Next(offset))
if offset > 0 =>
{
stack.push(index + offset);
}
- &Line::Control(ControlInstruction::JmpBy(_, offset, _, false)) => {
+ &Instruction::JmpByCall(_, offset, _) => {
stack.push(index + offset);
}
- &Line::Control(ControlInstruction::JmpBy(_, offset, _, true)) => {
+ &Instruction::JmpByExecute(_, offset, _) => {
stack.push(index + offset);
return true;
}
- &Line::Control(ControlInstruction::Proceed)
- | &Line::Control(ControlInstruction::CallClause(_, _, _, true, _)) => {
+ &Instruction::Proceed => {
return true;
}
- &Line::Control(ControlInstruction::RevJmpBy(offset)) => {
+ &Instruction::RevJmpBy(offset) => {
if offset > 0 {
stack.push(index - offset);
} else {
return true;
}
}
+ instr if instr.is_execute() => {
+ return true;
+ }
_ => {}
};
* begin in code at the offset p. Each instruction is passed to the
* walker function.
*/
-pub(crate) fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Line)) {
+pub(crate) fn walk_code(code: &Code, p: usize, mut walker: impl FnMut(&Instruction)) {
let mut stack = vec![p];
let mut visited_indices = IndexSet::new();
);
let payload = BootstrappingLoadState(
- LoadStatePayload::new(wam_prelude.code_repo.code.len(), term_stream)
+ LoadStatePayload::new(wam_prelude.code.len(), term_stream)
);
let loader: Loader<'_, BootstrappingLoadState> = Loader { payload, wam_prelude };
let code_len = code.len();
match &mut code[jmp_by_offset] {
- &mut Line::Control(ControlInstruction::JmpBy(_, ref mut offset, ..)) => {
+ &mut Instruction::JmpByCall(_, ref mut offset, ..) |
+ &mut Instruction::JmpByExecute(_, ref mut offset, ..) => {
*offset = code_len - jmp_by_offset;
}
_ => {
retraction_info: &mut RetractionInfo,
) -> Option<usize> {
match &mut code[index] {
- Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(0))) => None,
- Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(ref mut o))) => {
+ Instruction::DynamicElse(_, _, NextOrFail::Next(0)) => None,
+ Instruction::DynamicElse(_, _, NextOrFail::Next(ref mut o)) => {
retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(index, *o));
Some(mem::replace(o, 0))
}
- Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(0))) => None,
- Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(ref mut o))) => {
+ Instruction::DynamicInternalElse(_, _, NextOrFail::Next(0)) => None,
+ Instruction::DynamicInternalElse(_, _, NextOrFail::Next(ref mut o)) => {
retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(index, *o));
Some(mem::replace(o, 0))
}
- Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Fail(_)))
- | Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Fail(_))) => None,
- Line::Choice(ChoiceInstruction::TryMeElse(0)) => None,
- Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
+ Instruction::DynamicElse(_, _, NextOrFail::Fail(_)) |
+ Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(_)) => None,
+ Instruction::TryMeElse(0) => None,
+ Instruction::TryMeElse(ref mut o) => {
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(index, *o));
Some(mem::replace(o, 0))
}
let clause_loc =
find_inner_choice_instr(code, skeleton[clause_index].clause_start, index_loc);
- let target_indexing_line = to_indexing_line_mut(&mut code[target_index_loc]).unwrap();
+ let target_indexing_line = code[target_index_loc].to_indexing_line_mut().unwrap();
skeleton[clause_index]
.opt_arg_index_key
fn find_outer_choice_instr(code: &Code, mut index: usize) -> usize {
loop {
match &code[index] {
- Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(i)))
- | Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(i)))
+ Instruction::DynamicElse(_, _, NextOrFail::Next(i)) |
+ Instruction::DynamicInternalElse(_, _, NextOrFail::Next(i))
if *i > 0 =>
{
index += i;
fn find_inner_choice_instr(code: &Code, mut index: usize, index_loc: usize) -> usize {
loop {
match &code[index] {
- Line::Choice(ChoiceInstruction::TryMeElse(o))
- | Line::Choice(ChoiceInstruction::RetryMeElse(o)) => {
+ Instruction::TryMeElse(o) |
+ Instruction::RetryMeElse(o) => {
if *o > 0 {
return index;
} else {
index = index_loc;
}
}
- &Line::Choice(ChoiceInstruction::DynamicElse(_, _, next_or_fail)) => match next_or_fail
+ &Instruction::DynamicElse(_, _, next_or_fail) => match next_or_fail
{
NextOrFail::Next(i) => {
if i == 0 {
index = index_loc;
}
},
- &Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, next_or_fail)) => {
+ &Instruction::DynamicInternalElse(_, _, next_or_fail) => {
match next_or_fail {
NextOrFail::Next(i) => {
if i == 0 {
}
}
}
- Line::Choice(ChoiceInstruction::TrustMe(_)) => {
+ Instruction::TrustMe(_) => {
return index;
}
- Line::IndexingCode(indexing_code) => match &indexing_code[0] {
+ Instruction::IndexingCode(indexing_code) => match &indexing_code[0] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, ..)) => match v {
IndexingCodePtr::External(v) => {
index += v;
}
IndexingCodePtr::DynamicExternal(v) => match &code[index + v] {
- &Line::Choice(ChoiceInstruction::DynamicInternalElse(
+ &Instruction::DynamicInternalElse(
_,
_,
NextOrFail::Next(0),
- )) => {
+ ) => {
return index + v;
}
_ => {
unreachable!();
}
},
- Line::Control(ControlInstruction::RevJmpBy(offset)) => {
+ Instruction::RevJmpBy(offset) => {
index -= offset;
}
_ => {
) {
if let Some(index_loc) = opt_arg_index_key.switch_on_term_loc() {
let clause_start = find_inner_choice_instr(code, clause_start, index_loc);
-
- let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap();
-
+ let target_indexing_line = code[index_loc].to_indexing_line_mut().unwrap();
let offset = clause_start - index_loc + 1;
remove_index(opt_arg_index_key, target_indexing_line, offset);
);
match &mut code[inner_try_me_else_loc] {
- Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
+ Instruction::TryMeElse(ref mut o) => {
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(
inner_try_me_else_loc,
*o,
match *o {
0 => {
- code[inner_try_me_else_loc] = Line::Choice(ChoiceInstruction::TrustMe(0));
+ code[inner_try_me_else_loc] = Instruction::TrustMe(0);
}
o => match &code[inner_try_me_else_loc + o] {
- Line::Control(ControlInstruction::RevJmpBy(0)) => {
- code[inner_try_me_else_loc] = Line::Choice(ChoiceInstruction::TrustMe(o));
+ Instruction::RevJmpBy(0) => {
+ code[inner_try_me_else_loc] = Instruction::TrustMe(o);
}
_ => {
code[inner_try_me_else_loc] =
- Line::Choice(ChoiceInstruction::RetryMeElse(o));
+ Instruction::RetryMeElse(o);
}
},
}
);
}
None => match &mut code[outer_threaded_choice_instr_loc] {
- Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
+ Instruction::TryMeElse(ref mut o) => {
retraction_info
.push_record(RetractionRecord::ModifiedTryMeElse(inner_trust_me_loc, *o));
) -> usize {
loop {
match &mut code[instr_loc] {
- Line::Choice(ChoiceInstruction::RetryMeElse(o)) => {
+ Instruction::RetryMeElse(o) => {
retraction_info.push_record(RetractionRecord::ModifiedRetryMeElse(instr_loc, *o));
-
- code[instr_loc] = Line::Choice(ChoiceInstruction::TryMeElse(*o));
-
+ code[instr_loc] = Instruction::TryMeElse(*o);
return instr_loc;
}
- Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(_)))
- | Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(_))) => {
+ Instruction::DynamicElse(_, _, NextOrFail::Next(_)) |
+ Instruction::DynamicInternalElse(_, _, NextOrFail::Next(_)) => {
return instr_loc;
}
- &mut Line::Choice(ChoiceInstruction::DynamicElse(b, d, NextOrFail::Fail(o))) => {
+ &mut Instruction::DynamicElse(b, d, NextOrFail::Fail(o)) => {
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(
instr_loc,
NextOrFail::Fail(o),
));
- code[instr_loc] =
- Line::Choice(ChoiceInstruction::DynamicElse(b, d, NextOrFail::Next(0)));
-
+ code[instr_loc] = Instruction::DynamicElse(b, d, NextOrFail::Next(0));
return instr_loc;
}
- &mut Line::Choice(ChoiceInstruction::DynamicInternalElse(
+ &mut Instruction::DynamicInternalElse(
b,
d,
NextOrFail::Fail(o),
- )) => {
+ ) => {
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(
instr_loc,
NextOrFail::Fail(o),
));
- code[instr_loc] = Line::Choice(ChoiceInstruction::DynamicInternalElse(
+ code[instr_loc] = Instruction::DynamicInternalElse(
b,
d,
NextOrFail::Next(0),
- ));
+ );
return instr_loc;
}
- Line::Choice(ChoiceInstruction::TrustMe(o)) => {
- retraction_info
- .push_record(RetractionRecord::AppendedTrustMe(instr_loc, *o, false));
+ Instruction::TrustMe(o) => {
+ retraction_info.push_record(RetractionRecord::AppendedTrustMe(instr_loc, *o, false));
- code[instr_loc] = Line::Choice(ChoiceInstruction::TryMeElse(0));
+ code[instr_loc] = Instruction::TryMeElse(0);
return instr_loc + 1;
}
- Line::Choice(ChoiceInstruction::TryMeElse(0)) => {
+ Instruction::TryMeElse(0) => {
return instr_loc + 1;
}
- Line::Choice(ChoiceInstruction::TryMeElse(o)) => {
+ Instruction::TryMeElse(o) => {
instr_loc += *o;
}
- Line::Control(ControlInstruction::RevJmpBy(o)) => {
+ Instruction::RevJmpBy(o) => {
instr_loc -= *o;
}
_ => {
offset: usize,
retraction_info: &mut RetractionInfo,
) {
- let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap();
+ let target_indexing_line = code[index_loc].to_indexing_line_mut().unwrap();
let v = match &target_indexing_line[0] {
&IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, ..)) => match v {
};
match &code[index_loc + v] {
- Line::Choice(ChoiceInstruction::TryMeElse(_))
- | Line::Choice(ChoiceInstruction::DynamicElse(..))
- | Line::Choice(ChoiceInstruction::DynamicInternalElse(..)) => {}
+ Instruction::TryMeElse(_) |
+ Instruction::DynamicElse(..) |
+ Instruction::DynamicInternalElse(..) => {}
_ => {
set_switch_var_offset(code, index_loc, offset, retraction_info);
}
offset: usize,
retraction_info: &mut RetractionInfo,
) {
- let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap();
+ let target_indexing_line = code[index_loc].to_indexing_line_mut().unwrap();
let old_v = match &mut target_indexing_line[0] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, ref mut v, ..)) => match *v {
retraction_info: &mut RetractionInfo,
) {
match &mut code[instr_loc] {
- Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Fail(_)))
- | Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Fail(_))) => {}
- Line::Choice(ChoiceInstruction::DynamicElse(_, _, ref mut o @ NextOrFail::Next(0))) => {
+ Instruction::DynamicElse(_, _, NextOrFail::Fail(_)) |
+ Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(_)) => {
+ }
+ Instruction::DynamicElse(_, _, ref mut o @ NextOrFail::Next(0)) => {
retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, 0));
*o = NextOrFail::Fail(0);
}
- &mut Line::Choice(ChoiceInstruction::DynamicElse(b, d, NextOrFail::Next(o))) => {
+ &mut Instruction::DynamicElse(b, d, NextOrFail::Next(o)) => {
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(
instr_loc,
NextOrFail::Next(o),
));
match &mut code[instr_loc + o] {
- Line::Control(ControlInstruction::RevJmpBy(p)) if *p == 0 => {
- code[instr_loc] =
- Line::Choice(ChoiceInstruction::DynamicElse(b, d, NextOrFail::Fail(o)));
+ Instruction::RevJmpBy(p) if *p == 0 => {
+ code[instr_loc] = Instruction::DynamicElse(b, d, NextOrFail::Fail(o));
}
_ => {
- code[instr_loc] =
- Line::Choice(ChoiceInstruction::DynamicElse(b, d, NextOrFail::Next(o)));
+ code[instr_loc] = Instruction::DynamicElse(b, d, NextOrFail::Next(o));
}
}
}
- Line::Choice(ChoiceInstruction::DynamicInternalElse(
- _,
- _,
- ref mut o @ NextOrFail::Next(0),
- )) => {
+ Instruction::DynamicInternalElse(_, _, ref mut o @ NextOrFail::Next(0)) => {
retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, 0));
*o = NextOrFail::Fail(0);
}
- &mut Line::Choice(ChoiceInstruction::DynamicInternalElse(b, d, NextOrFail::Next(o))) => {
+ &mut Instruction::DynamicInternalElse(b, d, NextOrFail::Next(o)) => {
retraction_info.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, o));
match &mut code[instr_loc + o] {
- Line::Control(ControlInstruction::RevJmpBy(p)) if *p == 0 => {
- code[instr_loc] = Line::Choice(ChoiceInstruction::DynamicInternalElse(
+ Instruction::RevJmpBy(p) if *p == 0 => {
+ code[instr_loc] = Instruction::DynamicInternalElse(
b,
d,
NextOrFail::Fail(o),
- ));
+ );
}
_ => {
- code[instr_loc] = Line::Choice(ChoiceInstruction::DynamicInternalElse(
+ code[instr_loc] = Instruction::DynamicInternalElse(
b,
d,
NextOrFail::Next(o),
- ));
+ );
}
}
}
- Line::Choice(ChoiceInstruction::TryMeElse(0)) => {
+ Instruction::TryMeElse(0) => {
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(instr_loc, 0));
- code[instr_loc] = Line::Choice(ChoiceInstruction::TrustMe(0));
+ code[instr_loc] = Instruction::TrustMe(0);
}
- Line::Choice(ChoiceInstruction::TryMeElse(o)) => {
+ Instruction::TryMeElse(o) => {
let o = *o;
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(instr_loc, o));
match &mut code[instr_loc + o] {
- Line::Control(ControlInstruction::RevJmpBy(p)) if *p == 0 => {
- code[instr_loc] = Line::Choice(ChoiceInstruction::TrustMe(o));
+ Instruction::RevJmpBy(p) if *p == 0 => {
+ code[instr_loc] = Instruction::TrustMe(o);
}
_ => {
- code[instr_loc] = Line::Choice(ChoiceInstruction::RetryMeElse(o));
+ code[instr_loc] = Instruction::RetryMeElse(o);
}
}
}
) {
loop {
match &mut code[instr_loc] {
- Line::Choice(ChoiceInstruction::TryMeElse(ref mut o))
- | Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o))
+ Instruction::TryMeElse(ref mut o) | Instruction::RetryMeElse(ref mut o)
if target_loc >= instr_loc =>
{
retraction_info.push_record(RetractionRecord::ReplacedChoiceOffset(instr_loc, *o));
*o = target_loc - instr_loc;
return;
}
- Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(ref mut o)))
- | Line::Choice(ChoiceInstruction::DynamicInternalElse(
+ Instruction::DynamicElse(_, _, NextOrFail::Next(ref mut o)) |
+ Instruction::DynamicInternalElse(
_,
_,
NextOrFail::Next(ref mut o),
- )) if target_loc >= instr_loc => {
+ ) if target_loc >= instr_loc => {
retraction_info
.push_record(RetractionRecord::ReplacedDynamicElseOffset(instr_loc, *o));
*o = target_loc - instr_loc;
return;
}
- Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Next(o)))
- | Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Next(o))) => {
+ Instruction::DynamicElse(_, _, NextOrFail::Next(o)) |
+ Instruction::DynamicInternalElse(_, _, NextOrFail::Next(o)) => {
instr_loc += *o;
}
- Line::Choice(ChoiceInstruction::TryMeElse(o))
- | Line::Choice(ChoiceInstruction::RetryMeElse(o)) => {
+ Instruction::TryMeElse(o)
+ | Instruction::RetryMeElse(o) => {
instr_loc += *o;
}
- Line::Control(ControlInstruction::RevJmpBy(ref mut o)) if instr_loc >= target_loc => {
+ Instruction::RevJmpBy(ref mut o) if instr_loc >= target_loc => {
retraction_info.push_record(RetractionRecord::ModifiedRevJmpBy(instr_loc, *o));
*o = instr_loc - target_loc;
return;
}
- &mut Line::Control(ControlInstruction::RevJmpBy(o)) => {
+ &mut Instruction::RevJmpBy(o) => {
instr_loc -= o;
}
- &mut Line::Choice(ChoiceInstruction::DynamicElse(birth, death, ref mut fail))
+ &mut Instruction::DynamicElse(birth, death, ref mut fail)
if target_loc >= instr_loc =>
{
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(instr_loc, *fail));
- code[instr_loc] = Line::Choice(ChoiceInstruction::DynamicElse(
+ code[instr_loc] = instr!("dynamic_else",
birth,
death,
- NextOrFail::Next(target_loc - instr_loc),
- ));
+ NextOrFail::Next(target_loc - instr_loc)
+ );
return;
}
- Line::Choice(ChoiceInstruction::DynamicElse(_, _, NextOrFail::Fail(o))) if *o > 0 => {
+ Instruction::DynamicElse(_, _, NextOrFail::Fail(o)) if *o > 0 => {
instr_loc += *o;
}
- &mut Line::Choice(ChoiceInstruction::DynamicInternalElse(
+ &mut Instruction::DynamicInternalElse(
birth,
death,
ref mut fail,
- )) if target_loc >= instr_loc => {
+ ) if target_loc >= instr_loc => {
retraction_info.push_record(RetractionRecord::AppendedNextOrFail(instr_loc, *fail));
- code[instr_loc] = Line::Choice(ChoiceInstruction::DynamicInternalElse(
+ code[instr_loc] = instr!("dynamic_internal_else",
birth,
death,
- NextOrFail::Next(target_loc - instr_loc),
- ));
+ NextOrFail::Next(target_loc - instr_loc)
+ );
return;
}
- Line::Choice(ChoiceInstruction::DynamicInternalElse(_, _, NextOrFail::Fail(o)))
+ Instruction::DynamicInternalElse(_, _, NextOrFail::Fail(o))
if *o > 0 =>
{
instr_loc += *o;
}
- Line::Choice(ChoiceInstruction::TrustMe(ref mut o)) if target_loc >= instr_loc => {
+ Instruction::TrustMe(ref mut o) if target_loc >= instr_loc => {
retraction_info.push_record(
RetractionRecord::AppendedTrustMe(instr_loc, *o, false),
//choice_instr.is_default()),
);
- code[instr_loc] =
- Line::Choice(ChoiceInstruction::RetryMeElse(target_loc - instr_loc));
-
+ code[instr_loc] = instr!("retry_me_else", target_loc - instr_loc);
return;
}
- Line::Choice(ChoiceInstruction::TrustMe(o)) if *o > 0 => {
+ Instruction::TrustMe(o) if *o > 0 => {
instr_loc += *o;
}
_ => {
retraction_info: &mut RetractionInfo,
) -> Option<IndexPtr> {
match &mut code[non_indexed_choice_instr_loc] {
- Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o)) => {
+ Instruction::RetryMeElse(ref mut o) => {
let o = *o;
thread_choice_instr_at_to(
None
}
- Line::Choice(ChoiceInstruction::TrustMe(_)) => {
+ Instruction::TrustMe(_) => {
match &mut code[preceding_choice_instr_loc] {
- Line::Choice(ChoiceInstruction::RetryMeElse(o)) => {
+ Instruction::RetryMeElse(o) => {
retraction_info.push_record(RetractionRecord::ModifiedRetryMeElse(
preceding_choice_instr_loc,
*o,
));
- code[preceding_choice_instr_loc] = Line::Choice(ChoiceInstruction::TrustMe(0));
+ code[preceding_choice_instr_loc] = Instruction::TrustMe(0);
None
}
- Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
+ Instruction::TryMeElse(ref mut o) => {
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(
preceding_choice_instr_loc,
*o,
retraction_info: &mut RetractionInfo,
) -> Option<IndexPtr> {
match &mut code[non_indexed_choice_instr_loc] {
- Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) => {
+ Instruction::TryMeElse(ref mut o) => {
if *o > 0 {
retraction_info.push_record(RetractionRecord::ModifiedTryMeElse(
non_indexed_choice_instr_loc,
fn find_dynamic_outer_choice_instr(code: &Code, index_loc: usize) -> usize {
match &code[index_loc] {
- Line::IndexingCode(indexing_code) => match &indexing_code[0] {
+ Instruction::IndexingCode(indexing_code) => match &indexing_code[0] {
&IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(
_,
IndexingCodePtr::DynamicExternal(v),
let inner_thread_rev_offset =
3 + prepend_queue.len() + clause_loc - skeleton.clauses[1].clause_start;
- prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy(
- inner_thread_rev_offset,
- )));
+ prepend_queue.push_back(Instruction::RevJmpBy(inner_thread_rev_offset));
- prepend_queue.push_front(Line::Choice(
- settings.internal_try_me_else(prepend_queue.len()),
- ));
+ prepend_queue.push_front(settings.internal_try_me_else(prepend_queue.len()));
// prepend_queue is now:
// | TryMeElse N_2
// | (clause_code)
// +N_2 | RevJmpBy (RetryMeElse(M_1) or TryMeElse(0) at index_loc + 1)
- prepend_queue.push_front(Line::Control(ControlInstruction::RevJmpBy(
- 1 + clause_loc - index_loc,
- )));
+ prepend_queue.push_front(Instruction::RevJmpBy(1 + clause_loc - index_loc));
let outer_thread_choice_offset = // outer_thread_choice_loc WAS index_loc - 1..
match derelictize_try_me_else(code, outer_thread_choice_loc, retraction_info) {
next_subseq_offset;
prepend_queue.push_back(
- Line::Control(ControlInstruction::RevJmpBy(outer_thread_rev_offset))
+ Instruction::RevJmpBy(outer_thread_rev_offset)
);
prepend_queue.len()
// awaiting the addition of unindexed
// clauses.
- prepend_queue.push_back(
- Line::Control(ControlInstruction::RevJmpBy(0)),
- );
+ prepend_queue.push_back(Instruction::RevJmpBy(0));
0
}
};
- prepend_queue.push_front(Line::Choice(
- settings.try_me_else(outer_thread_choice_offset),
- ));
+ prepend_queue.push_front(settings.try_me_else(outer_thread_choice_offset));
// prepend_queue is now:
// | TryMeElse N_3
// N_2 | RevJmpBy (RetryMeElse(M_1) or TryMeElse(0) at index_loc + 1)
// N_3 | RevJmpBy (TryMeElse(N_1) at index_loc - 1 or TrustMe if N_1 == 0)
- let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap();
+ let target_indexing_line = code[index_loc].to_indexing_line_mut().unwrap();
merge_clause_index(
target_indexing_line,
// this is a stub for chaining inner-threaded choice
// instructions.
- prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy(0)));
+ prepend_queue.push_back(Instruction::RevJmpBy(0));
let prepend_queue_len = prepend_queue.len();
match &mut prepend_queue[1] {
- Line::Choice(ChoiceInstruction::TryMeElse(ref mut o)) if *o == 0 => {
+ Instruction::TryMeElse(ref mut o) if *o == 0 => {
*o = prepend_queue_len - 2;
}
- Line::Choice(ChoiceInstruction::DynamicInternalElse(
+ Instruction::DynamicInternalElse(
_,
_,
ref mut o @ NextOrFail::Next(0),
- )) => {
+ ) => {
*o = NextOrFail::Fail(prepend_queue_len - 2);
}
_ => {
}
}
- prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy(
- inner_thread_rev_offset,
- )));
-
- prepend_queue.push_front(Line::Choice(settings.try_me_else(prepend_queue.len())));
+ prepend_queue.push_back(Instruction::RevJmpBy(inner_thread_rev_offset));
+ prepend_queue.push_front(settings.try_me_else(prepend_queue.len()));
// prepend_queue is now:
// | TryMeElse(N_2)
let inner_thread_rev_offset =
1 + prepend_queue.len() + clause_loc - old_clause_start;
- prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy(
- inner_thread_rev_offset,
- )));
-
- prepend_queue.push_front(Line::Choice(settings.try_me_else(prepend_queue.len())));
+ prepend_queue.push_back(Instruction::RevJmpBy(inner_thread_rev_offset));
+ prepend_queue.push_front(settings.try_me_else(prepend_queue.len()));
// prepend_queue is now:
// | TryMeElse(N_2)
let inner_thread_rev_offset =
1 + prepend_queue.len() + clause_loc - old_clause_start;
- prepend_queue.push_back(Line::Control(ControlInstruction::RevJmpBy(
- inner_thread_rev_offset,
- )));
-
- prepend_queue.push_front(Line::Choice(settings.try_me_else(prepend_queue.len())));
+ prepend_queue.push_back(Instruction::RevJmpBy(inner_thread_rev_offset));
+ prepend_queue.push_front(settings.try_me_else(prepend_queue.len()));
// prepend_queue is now:
// | TryMeElse(N_2)
.switch_on_term_loc()
{
Some(index_loc) if lower_bound_arg_num == target_arg_num => {
- code.push(Line::Choice(settings.internal_trust_me()));
+ code.push(settings.internal_trust_me());
code.extend(clause_code.drain(3..)); // skip the indexing code
skeleton.clauses[target_pos].clause_start,
));
- let target_indexing_line = to_indexing_line_mut(&mut code[index_loc]).unwrap();
+ let target_indexing_line = code[index_loc].to_indexing_line_mut().unwrap();
merge_clause_index(
target_indexing_line,
target_pos_clause_start // skeleton.clauses[target_pos - 1].clause_start
}
_ => {
- code.push(Line::Choice(settings.trust_me()));
+ code.push(settings.trust_me());
skeleton.clauses[target_pos].opt_arg_index_key += clause_loc;
code.extend(clause_code.drain(1..));
key: &PredicateKey,
is_dynamic: bool,
) {
- if let CompilationTarget::Module(ref module_name) = compilation_target {
- match module_name.as_str() {
- "builtins" | "loader" => return,
+ if let CompilationTarget::Module(module_name) = compilation_target {
+ match module_name {
+ atom!("builtins") | atom!("loader") => return,
_ => {}
}
}
) -> Result<CodeIndex, SessionError> {
let code_index = self.get_or_insert_code_index(key, predicates.compilation_target);
- let code_len = self.wam_prelude.code_repo.code.len();
+ let code_len = self.wam_prelude.code.len();
let mut code_ptr = code_len;
let mut clauses = vec![];
}
match &mut code[0] {
- Line::Choice(ChoiceInstruction::TryMeElse(0)) => {
+ Instruction::TryMeElse(0) => {
code_ptr += 1;
}
_ => {}
index_ptr,
);
- self.wam_prelude.code_repo.code.extend(code.into_iter());
+ self.wam_prelude.code.extend(code.into_iter());
Ok(code_index)
}
mut standalone_skeleton,
} = self.compile_standalone_clause(clause, settings)?;
- let code_len = self.wam_prelude.code_repo.code.len();
+ let code_len = self.wam_prelude.code.len();
let skeleton = match self
.wam_prelude
let global_clock = LS::machine_st(&mut self.payload).global_clock;
let result = append_compiled_clause(
- &mut self.wam_prelude.code_repo.code,
+ &mut self.wam_prelude.code,
clause_code,
skeleton,
&mut self.payload.retraction_info,
let global_clock = LS::machine_st(&mut self.payload).global_clock;
let new_code_ptr = prepend_compiled_clause(
- &mut self.wam_prelude.code_repo.code,
+ &mut self.wam_prelude.code,
compilation_target,
key,
clause_code,
.switch_on_term_loc()
{
Some(index_loc) => find_inner_choice_instr(
- &self.wam_prelude.code_repo.code,
+ &self.wam_prelude.code,
skeleton.clauses[target_pos].clause_start,
index_loc,
),
None => skeleton.clauses[target_pos].clause_start,
};
- match &mut self.wam_prelude.code_repo.code[clause_loc] {
- Line::Choice(ChoiceInstruction::DynamicElse(_, ref mut d, _))
- | Line::Choice(ChoiceInstruction::DynamicInternalElse(_, ref mut d, _)) => {
+ match &mut self.wam_prelude.code[clause_loc] {
+ Instruction::DynamicElse(_, ref mut d, _) |
+ Instruction::DynamicInternalElse(_, ref mut d, _) => {
*d = Death::Finite(LS::machine_st(&mut self.payload).global_clock);
}
_ => unreachable!(),
}
};
- let code = &mut self.wam_prelude.code_repo.code;
+ let code = &mut self.wam_prelude.code;
let lower_bound = lower_bound_of_target_clause(skeleton, target_pos);
let lower_bound_is_unindexed = !skeleton.clauses[lower_bound].opt_arg_index_key.is_some();
Some(later_indexing_loc) if later_indexing_loc < target_indexing_loc => {
let target_indexing_line = mem::replace(
&mut code[target_indexing_loc],
- Line::Control(ControlInstruction::RevJmpBy(
- target_indexing_loc - later_indexing_loc,
- )),
+ Instruction::RevJmpBy(target_indexing_loc - later_indexing_loc),
);
match target_indexing_line {
- Line::IndexingCode(indexing_code) => {
+ Instruction::IndexingCode(indexing_code) => {
self.payload.retraction_info.push_record(
RetractionRecord::ReplacedIndexingLine(
target_indexing_loc,
);
match &mut code[preceding_choice_instr_loc] {
- Line::Choice(ChoiceInstruction::TryMeElse(0)) => {
+ Instruction::TryMeElse(0) => {
set_switch_var_offset(
code,
index_loc,
use crate::instructions::*;
use crate::machine::*;
use crate::machine::arithmetic_ops::*;
-use crate::machine::code_repo::*;
use crate::machine::machine_errors::*;
use crate::machine::machine_state::*;
use crate::types::*;
use crate::try_numeric_result;
-impl Machine {
- #[inline(always)]
- pub(super) fn dispatch_instr(&mut self, instr: OwnedOrIndexed) {
- match instr.as_ref(&self.code_repo.code) {
- &Line::Arithmetic(ref arith_instr) => {
- let stub_gen = || functor_stub(atom!("is"), 2);
-
- match arith_instr {
- &ArithmeticInstruction::Add(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
-
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- try_numeric_result!(add(n1, n2, &mut self.machine_st.arena), stub_gen)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Sub(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+macro_rules! step_or_fail {
+ ($self:expr, $step_e:expr) => {
+ if $self.machine_st.fail {
+ $self.machine_st.backtrack();
+ } else {
+ $step_e;
+ }
+ };
+}
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- try_numeric_result!(sub(n1, n2, &mut self.machine_st.arena), stub_gen)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Mul(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+macro_rules! try_or_throw {
+ ($s:expr, $e:expr) => {{
+ match $e {
+ Ok(val) => val,
+ Err(msg) => {
+ $s.throw_exception(msg);
+ $s.backtrack();
+ continue;
+ }
+ }
+ }};
+}
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- try_numeric_result!(mul(n1, n2, &mut self.machine_st.arena), stub_gen)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Max(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+macro_rules! try_or_throw_gen {
+ ($s:expr, $e:expr) => {{
+ match $e {
+ Ok(val) => val,
+ Err(msg_fn) => {
+ let e = msg_fn($s);
+ $s.throw_exception(e);
+ $s.backtrack();
+ continue;
+ }
+ }
+ }};
+}
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- max(n1, n2)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Min(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+static INSTRUCTIONS_PER_INTERRUPT_POLL: usize = 256;
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- min(n1, n2)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::IntPow(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+impl MachineState {
+ #[inline(always)]
+ fn compare(&mut self) -> CallResult {
+ let stub_gen = || functor_stub(atom!("compare"), 3);
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- int_pow(n1, n2, &mut self.machine_st.arena)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Gcd(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+ let a1 = self.store(self.deref(self.registers[1]));
+ let a2 = self.registers[2];
+ let a3 = self.registers[3];
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- gcd(n1, n2, &mut self.machine_st.arena)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Pow(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+ read_heap_cell!(a1,
+ (HeapCellValueTag::Str, s) => {
+ let (name, arity) = cell_as_atom_cell!(self.heap[s])
+ .get_name_and_arity();
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- pow(n1, n2, atom!("**"))
- );
- self.machine_st.p += 1;
+ match name {
+ atom!(">") | atom!("<") | atom!("=") if arity == 2 => {
}
- &ArithmeticInstruction::RDiv(ref a1, ref a2, t) => {
- let stub_gen = || functor_stub(atom!("(rdiv)"), 2);
-
- let r1 = try_or_fail!(self.machine_st, self.machine_st.get_rational(a1, stub_gen));
- let r2 = try_or_fail!(self.machine_st, self.machine_st.get_rational(a2, stub_gen));
-
- self.machine_st.interms[t - 1] = Number::Rational(arena_alloc!(
- try_or_fail_gen!(&mut self.machine_st, rdiv(r1, r2)),
- self.machine_st.arena
- ));
- self.machine_st.p += 1;
+ _ => {
+ let err = self.domain_error(DomainErrorType::Order, a1);
+ return Err(self.error_form(err, stub_gen()));
}
- &ArithmeticInstruction::IntFloorDiv(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+ }
+ }
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
+ }
+ _ => {
+ let err = self.type_error(ValidType::Atom, a1);
+ return Err(self.error_form(err, stub_gen()));
+ }
+ );
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- int_floor_div(n1, n2, &mut self.machine_st.arena)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::IDiv(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+ let atom = match compare_term_test!(self, a2, a3) {
+ Some(Ordering::Greater) => {
+ atom!(">")
+ }
+ Some(Ordering::Equal) => {
+ atom!("=")
+ }
+ None | Some(Ordering::Less) => {
+ atom!("<")
+ }
+ };
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- idiv(n1, n2, &mut self.machine_st.arena)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Abs(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ self.unify_atom(atom, a1);
+ Ok(())
+ }
- self.machine_st.interms[t - 1] = abs(n1, &mut self.machine_st.arena);
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Sign(ref a1, t) => {
- let n = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ pub fn copy_term(&mut self, attr_var_policy: AttrVarPolicy) {
+ let old_h = self.heap.len();
- self.machine_st.interms[t - 1] = sign(n);
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Neg(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ let a1 = self.registers[1];
+ let a2 = self.registers[2];
- self.machine_st.interms[t - 1] = neg(n1, &mut self.machine_st.arena);
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::BitwiseComplement(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ copy_term(CopyTerm::new(self), a1, attr_var_policy);
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- bitwise_complement(n1, &mut self.machine_st.arena)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Div(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+ unify_fn!(*self, heap_loc_as_cell!(old_h), a2);
+ }
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- div(n1, n2)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Shr(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+ fn sort(&mut self) -> CallResult {
+ self.check_sort_errors()?;
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- shr(n1, n2, &mut self.machine_st.arena)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Shl(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+ let stub_gen = || functor_stub(atom!("sort"), 2);
+ let mut list = self.try_from_list(self.registers[1], stub_gen)?;
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- shl(n1, n2, &mut self.machine_st.arena)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Xor(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+ list.sort_unstable_by(|v1, v2| {
+ compare_term_test!(self, *v1, *v2).unwrap_or(Ordering::Less)
+ });
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- xor(n1, n2, &mut self.machine_st.arena)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::And(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+ list.dedup_by(|v1, v2| {
+ compare_term_test!(self, *v1, *v2) == Some(Ordering::Equal)
+ });
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- and(n1, n2, &mut self.machine_st.arena)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Or(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+ let heap_addr = heap_loc_as_cell!(
+ iter_to_heap_list(&mut self.heap, list.into_iter())
+ );
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- or(n1, n2, &mut self.machine_st.arena)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Mod(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+ let target_addr = self.registers[2];
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- modulus(n1, n2, &mut self.machine_st.arena)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Rem(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+ unify_fn!(*self, target_addr, heap_addr);
+ Ok(())
+ }
- self.machine_st.interms[t - 1] = try_or_fail_gen!(
- &mut self.machine_st,
- remainder(n1, n2, &mut self.machine_st.arena)
- );
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Cos(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ fn keysort(&mut self) -> CallResult {
+ self.check_keysort_errors()?;
- self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
- try_or_fail_gen!(&mut self.machine_st, cos(n1))
- ));
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Sin(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ let stub_gen = || functor_stub(atom!("keysort"), 2);
+ let list = self.try_from_list(self.registers[1], stub_gen)?;
- self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
- try_or_fail_gen!(&mut self.machine_st, sin(n1))
- ));
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Tan(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ let mut key_pairs = Vec::with_capacity(list.len());
- self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
- try_or_fail_gen!(&mut self.machine_st, tan(n1))
- ));
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Sqrt(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ for val in list {
+ let key = self.project_onto_key(val)?;
+ key_pairs.push((key, val));
+ }
- self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
- try_or_fail_gen!(&mut self.machine_st, sqrt(n1))
- ));
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Log(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ key_pairs.sort_by(|a1, a2| {
+ compare_term_test!(self, a1.0, a2.0).unwrap_or(Ordering::Less)
+ });
- self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
- try_or_fail_gen!(&mut self.machine_st, log(n1))
- ));
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Exp(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ let key_pairs = key_pairs.into_iter().map(|kp| kp.1);
+ let heap_addr = heap_loc_as_cell!(
+ iter_to_heap_list(&mut self.heap, key_pairs)
+ );
- self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
- try_or_fail_gen!(&mut self.machine_st, exp(n1))
- ));
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::ACos(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ let target_addr = self.registers[2];
- self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
- try_or_fail_gen!(&mut self.machine_st, acos(n1))
- ));
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::ASin(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ unify_fn!(*self, target_addr, heap_addr);
+ Ok(())
+ }
- self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
- try_or_fail_gen!(&mut self.machine_st, asin(n1))
- ));
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::ATan(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ fn is(&mut self, r: RegType, at: ArithmeticTerm) -> CallResult {
+ let n1 = self.store(self.deref(self[r]));
- self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
- try_or_fail_gen!(&mut self.machine_st, atan(n1))
- ));
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::ATan2(ref a1, ref a2, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(a2));
+ match self.get_number(&at)? {
+ Number::Fixnum(n) => self.unify_fixnum(n, n1),
+ Number::Float(n) => {
+ // TODO: argghh.. allocate floats to their own area.
+ let n = arena_alloc!(n, &mut self.arena);
+ self.unify_f64(n, n1)
+ }
+ Number::Integer(n) => self.unify_big_int(n, n1),
+ Number::Rational(n) => self.unify_rational(n, n1),
+ }
- self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
- try_or_fail_gen!(&mut self.machine_st, atan2(n1, n2))
- ));
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Float(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ Ok(())
+ }
+}
- self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
- try_or_fail_gen!(&mut self.machine_st, float(n1))
- ));
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Truncate(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+impl Machine {
+ fn read(&mut self) -> CallResult {
+ let stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("read"),
+ 2,
+ )?;
+
+ match self.machine_st.read(stream, &self.indices.op_dir) {
+ Ok(offset) => {
+ let value = self.machine_st.registers[2];
+ unify_fn!(&mut self.machine_st, value, heap_loc_as_cell!(offset.heap_loc));
+ }
+ Err(ParserError::UnexpectedEOF) => {
+ let value = self.machine_st.registers[2];
+ self.machine_st.unify_atom(atom!("end_of_file"), value);
+ }
+ Err(e) => {
+ let stub = functor_stub(atom!("read"), 2);
+ let err = self.machine_st.syntax_error(e);
- self.machine_st.interms[t - 1] = truncate(n1, &mut self.machine_st.arena);
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Round(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ return Err(self.machine_st.error_form(err, stub));
+ }
+ };
- self.machine_st.interms[t - 1] =
- try_or_fail_gen!(&mut self.machine_st, round(n1, &mut self.machine_st.arena));
- self.machine_st.p += 1;
- }
- &ArithmeticInstruction::Ceiling(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
+ Ok(())
+ }
- self.machine_st.interms[t - 1] = ceiling(n1, &mut self.machine_st.arena);
- self.machine_st.p += 1;
+ pub(super) fn find_living_dynamic_else(&self, mut p: usize) -> Option<(usize, usize)> {
+ loop {
+ match &self.code[p] {
+ &Instruction::DynamicElse(
+ birth,
+ death,
+ NextOrFail::Next(i),
+ ) => {
+ if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
+ return Some((p, i));
+ } else if i > 0 {
+ p += i;
+ } else {
+ return None;
}
- &ArithmeticInstruction::Floor(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
-
- self.machine_st.interms[t - 1] = floor(n1, &mut self.machine_st.arena);
- self.machine_st.p += 1;
+ }
+ &Instruction::DynamicElse(
+ birth,
+ death,
+ NextOrFail::Fail(_),
+ ) => {
+ if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
+ return Some((p, 0));
+ } else {
+ return None;
}
- &ArithmeticInstruction::Plus(ref a1, t) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(a1));
-
- self.machine_st.interms[t - 1] = n1;
- self.machine_st.p += 1;
+ }
+ &Instruction::DynamicInternalElse(
+ birth,
+ death,
+ NextOrFail::Next(i),
+ ) => {
+ if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
+ return Some((p, i));
+ } else if i > 0 {
+ p += i;
+ } else {
+ return None;
+ }
+ }
+ &Instruction::DynamicInternalElse(
+ birth,
+ death,
+ NextOrFail::Fail(_),
+ ) => {
+ if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
+ return Some((p, 0));
+ } else {
+ return None;
}
}
+ &Instruction::RevJmpBy(i) => {
+ p -= i;
+ }
+ _ => {
+ unreachable!();
+ }
}
- &Line::Choice(ref choice_instr) => {
- match choice_instr {
- &ChoiceInstruction::DynamicElse(..) => {
- if let FirstOrNext::First = self.machine_st.dynamic_mode {
- self.machine_st.cc = self.machine_st.global_clock;
- }
-
- let p = self.machine_st.p.local().abs_loc();
+ }
+ }
- match self.find_living_dynamic_else(p) {
- Some((p, next_i)) => {
- self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
+ pub(super) fn find_living_dynamic(&self, oi: u32, mut ii: u32) -> Option<(usize, u32, u32, bool)> {
+ let p = self.machine_st.p;
- match self.machine_st.dynamic_mode {
- FirstOrNext::First if next_i == 0 => {
- self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p + 1));
- }
- FirstOrNext::First => {
- self.machine_st.cc = self.machine_st.global_clock;
+ let indexed_choice_instrs = match &self.code[p] {
+ Instruction::IndexingCode(ref indexing_code) => match &indexing_code[oi as usize] {
+ IndexingLine::DynamicIndexedChoice(ref indexed_choice_instrs) => {
+ indexed_choice_instrs
+ }
+ _ => unreachable!(),
+ },
+ _ => unreachable!(),
+ };
+
+ loop {
+ match &indexed_choice_instrs.get(ii as usize) {
+ Some(&offset) => match &self.code[p + offset - 1] {
+ &Instruction::DynamicInternalElse(
+ birth,
+ death,
+ next_or_fail,
+ ) => {
+ if birth < self.machine_st.cc && Death::Finite(self.machine_st.cc) <= death {
+ return Some((offset, oi, ii, next_or_fail.is_next()));
+ } else {
+ ii += 1;
+ }
+ }
+ _ => unreachable!(),
+ },
+ None => return None,
+ }
+ }
+ }
- match self.find_living_dynamic_else(p + next_i) {
- Some(_) => {
- self.machine_st.registers[self.machine_st.num_of_args + 1] =
- fixnum_as_cell!(Fixnum::build_with(self.machine_st.cc as i64));
+ #[inline(always)]
+ fn execute_switch_on_term(&mut self) {
+ #[inline(always)]
+ fn dynamic_external_of_clause_is_valid(machine: &mut Machine, p: usize) -> bool {
+ match &machine.code[p] {
+ Instruction::DynamicInternalElse(..) => {
+ machine.machine_st.dynamic_mode = FirstOrNext::First;
+ return true;
+ }
+ _ => {}
+ }
- self.machine_st.num_of_args += 1;
- self.machine_st.try_me_else(next_i);
- self.machine_st.num_of_args -= 1;
- }
- None => {
- self.machine_st.p += 1;
- }
- }
- }
- FirstOrNext::Next => {
- let n = self.machine_st
- .stack
- .index_or_frame(self.machine_st.b)
- .prelude
- .univ_prelude
- .num_cells;
-
- self.machine_st.cc = cell_as_fixnum!(
- self.machine_st.stack[stack_loc!(OrFrame, self.machine_st.b, n-1)]
- ).get_num() as usize;
-
- if next_i > 0 {
- match self.find_living_dynamic_else(p + next_i) {
- Some(_) => {
- self.retry_me_else(next_i);
+ match &machine.code[p - 1] {
+ &Instruction::DynamicInternalElse(birth, death, _) => {
+ if birth < machine.machine_st.cc && Death::Finite(machine.machine_st.cc) <= death {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ _ => {}
+ }
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- None => {
- self.trust_me();
+ true
+ }
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- }
- } else {
- self.trust_me();
+ let indexing_lines = self.code[self.machine_st.p].to_indexing_line_mut().unwrap();
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- }
+ let mut index = 0;
+ let addr = match &indexing_lines[0] {
+ &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(arg, ..)) => {
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[arg]))
+ }
+ _ => {
+ unreachable!()
+ }
+ };
+
+ loop {
+ match &indexing_lines[index] {
+ &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, c, l, s)) => {
+ let offset = read_heap_cell!(addr,
+ (HeapCellValueTag::Var |
+ HeapCellValueTag::StackVar |
+ HeapCellValueTag::AttrVar) => {
+ v
+ }
+ (HeapCellValueTag::PStrLoc |
+ HeapCellValueTag::Lis |
+ HeapCellValueTag::CStr) => {
+ l
+ }
+ (HeapCellValueTag::Fixnum |
+ HeapCellValueTag::Char |
+ HeapCellValueTag::F64) => {
+ c
+ }
+ (HeapCellValueTag::Atom, (_name, arity)) => {
+ // if arity == 0 { c } else { s }
+ debug_assert!(arity == 0);
+ c
+ }
+ (HeapCellValueTag::Str) => {
+ s
+ }
+ (HeapCellValueTag::Cons, ptr) => {
+ match ptr.get_tag() {
+ ArenaHeaderTag::Rational | ArenaHeaderTag::Integer |
+ ArenaHeaderTag::F64 => {
+ c
+ }
+ _ => {
+ IndexingCodePtr::Fail
}
- }
- None => {
- self.machine_st.fail = true;
}
}
+ _ => {
+ unreachable!();
+ }
+ );
- self.machine_st.dynamic_mode = FirstOrNext::Next;
- }
- &ChoiceInstruction::DynamicInternalElse(..) => {
- let p = self.machine_st.p.local().abs_loc();
-
- match self.find_living_dynamic_else(p) {
- Some((p, next_i)) => {
- self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
+ match offset {
+ IndexingCodePtr::Fail => {
+ self.machine_st.fail = true;
+ break;
+ }
+ IndexingCodePtr::DynamicExternal(o) => {
+ // either points directly to a
+ // DynamicInternalElse, or just ahead of
+ // one. Or neither!
+ let p = self.machine_st.p;
- match self.machine_st.dynamic_mode {
- FirstOrNext::First if next_i == 0 => {
- self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p + 1));
- }
- FirstOrNext::First => {
- match self.find_living_dynamic_else(p + next_i) {
- Some(_) => {
- self.machine_st.registers[self.machine_st.num_of_args + 1] =
- fixnum_as_cell!(Fixnum::build_with(self.machine_st.cc as i64));
+ if !dynamic_external_of_clause_is_valid(self, p + o) {
+ self.machine_st.fail = true;
+ } else {
+ self.machine_st.p += o;
+ }
- self.machine_st.num_of_args += 1;
- self.machine_st.try_me_else(next_i);
- self.machine_st.num_of_args -= 1;
- }
- None => {
- self.machine_st.p += 1;
- }
- }
- }
- FirstOrNext::Next => {
- let n = self.machine_st
- .stack
- .index_or_frame(self.machine_st.b)
- .prelude
- .univ_prelude
- .num_cells;
-
- self.machine_st.cc = cell_as_fixnum!(
- self.machine_st.stack[stack_loc!(OrFrame, self.machine_st.b, n-1)]
- ).get_num() as usize;
-
- if next_i > 0 {
- match self.find_living_dynamic_else(p + next_i) {
- Some(_) => {
- self.retry_me_else(next_i);
+ break;
+ }
+ IndexingCodePtr::External(o) => {
+ self.machine_st.p += o;
+ break;
+ }
+ IndexingCodePtr::Internal(o) => {
+ index += o;
+ }
+ }
+ }
+ &IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref hm)) => {
+ let lit = read_heap_cell!(addr,
+ (HeapCellValueTag::Char, c) => {
+ Literal::Char(c)
+ }
+ (HeapCellValueTag::Fixnum, n) => {
+ Literal::Fixnum(n)
+ }
+ (HeapCellValueTag::F64, f) => {
+ Literal::Float(f)
+ }
+ (HeapCellValueTag::Atom, (atom, arity)) => {
+ debug_assert_eq!(arity, 0);
+ Literal::Atom(atom)
+ }
+ (HeapCellValueTag::Cons, cons_ptr) => {
+ match_untyped_arena_ptr!(cons_ptr,
+ (ArenaHeaderTag::Rational, r) => {
+ Literal::Rational(r)
+ }
+ (ArenaHeaderTag::F64, f) => {
+ Literal::Float(F64Ptr(f))
+ }
+ (ArenaHeaderTag::Integer, n) => {
+ Literal::Integer(n)
+ }
+ _ => {
+ unreachable!()
+ }
+ )
+ }
+ _ => {
+ unreachable!()
+ }
+ );
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- None => {
- self.trust_me();
+ let offset = match hm.get(&lit) {
+ Some(offset) => *offset,
+ _ => IndexingCodePtr::Fail,
+ };
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- }
- } else {
- self.trust_me();
+ match offset {
+ IndexingCodePtr::Fail => {
+ self.machine_st.fail = true;
+ break;
+ }
+ IndexingCodePtr::DynamicExternal(o) => {
+ // either points directly to a
+ // DynamicInternalElse, or just ahead of
+ // one. Or neither!
+ let p = self.machine_st.p;
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- }
- }
- }
- None => {
+ if !dynamic_external_of_clause_is_valid(self, p + o) {
self.machine_st.fail = true;
+ } else {
+ self.machine_st.p += o;
}
- }
-
- self.machine_st.dynamic_mode = FirstOrNext::Next;
- }
- &ChoiceInstruction::TryMeElse(offset) => {
- self.machine_st.try_me_else(offset);
- }
- &ChoiceInstruction::DefaultRetryMeElse(offset) => {
- self.retry_me_else(offset);
- }
- &ChoiceInstruction::DefaultTrustMe(_) => {
- self.trust_me();
- }
- &ChoiceInstruction::RetryMeElse(offset) => {
- self.retry_me_else(offset);
-
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- &ChoiceInstruction::TrustMe(_) => {
- self.trust_me();
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
+ break;
+ }
+ IndexingCodePtr::External(o) => {
+ self.machine_st.p += o;
+ break;
+ }
+ IndexingCodePtr::Internal(o) => {
+ index += o;
+ }
}
}
- }
- &Line::Cut(ref cut_instr) => {
- match cut_instr {
- &CutInstruction::NeckCut => {
- let b = self.machine_st.b;
- let b0 = self.machine_st.b0;
-
- if b > b0 {
- self.machine_st.b = b0;
+ &IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref hm)) => {
+ let offset = read_heap_cell!(addr,
+ (HeapCellValueTag::Atom, (name, arity)) => {
+ match hm.get(&(name, arity)) {
+ Some(offset) => *offset,
+ None => IndexingCodePtr::Fail,
+ }
+ }
+ (HeapCellValueTag::Str, s) => {
+ let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
+ .get_name_and_arity();
- if b > self.machine_st.e {
- self.machine_st.stack.truncate(b);
+ match hm.get(&(name, arity)) {
+ Some(offset) => *offset,
+ None => IndexingCodePtr::Fail,
}
}
+ _ => {
+ IndexingCodePtr::Fail
+ }
+ );
- self.machine_st.p += 1;
- }
- &CutInstruction::GetLevel(r) => {
- let b0 = self.machine_st.b0;
-
- self.machine_st[r] = fixnum_as_cell!(Fixnum::build_with(b0 as i64));
- self.machine_st.p += 1;
- }
- &CutInstruction::GetLevelAndUnify(r) => {
- let b0 = self.machine_st[perm_v!(1)];
- let a = self.machine_st[r];
+ match offset {
+ IndexingCodePtr::Fail => {
+ self.machine_st.fail = true;
+ break;
+ }
+ IndexingCodePtr::DynamicExternal(o) => {
+ let p = self.machine_st.p;
- unify_fn!(&mut self.machine_st, a, b0);
- self.machine_st.p += 1;
- }
- &CutInstruction::Cut(r) => {
- let value = self.machine_st[r];
- self.machine_st.cut_body(value);
+ if !dynamic_external_of_clause_is_valid(self, p + o) {
+ self.machine_st.fail = true;
+ } else {
+ self.machine_st.p += o;
+ }
- if !self.machine_st.fail && !(self.machine_st.run_cleaners_fn)(self) {
- self.machine_st.p += 1;
+ break;
+ }
+ IndexingCodePtr::External(o) => {
+ self.machine_st.p += o;
+ break;
+ }
+ IndexingCodePtr::Internal(o) => {
+ index += o;
}
}
}
+ &IndexingLine::IndexedChoice(_) => {
+ self.machine_st.oip = index as u32;
+ self.machine_st.iip = 0;
+
+ break;
+ }
+ &IndexingLine::DynamicIndexedChoice(_) => {
+ self.machine_st.dynamic_mode = FirstOrNext::First;
+
+ self.machine_st.oip = index as u32;
+ self.machine_st.iip = 0;
+
+ break;
+ }
}
- &Line::Control(ref ctrl_instr) => {
- match ctrl_instr {
- &ControlInstruction::Allocate(num_cells) =>
- self.machine_st.allocate(num_cells),
- &ControlInstruction::CallClause(ref ct, arity, _, lco, use_default_cp) => {
- let interrupted = INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
-
- match INTERRUPT.compare_exchange(
- interrupted,
- false,
- std::sync::atomic::Ordering::Relaxed,
- std::sync::atomic::Ordering::Relaxed,
- ) {
- Ok(interruption) => {
- if interruption {
- self.machine_st.throw_interrupt_exception();
- return;
- }
- }
- Err(_) => unreachable!(),
- }
+ }
+ }
- self.machine_st.last_call = lco;
+ #[inline(always)]
+ pub(super) fn dispatch_loop(&mut self) {
+ 'outer: loop {
+ for _ in 0 .. INSTRUCTIONS_PER_INTERRUPT_POLL {
+ match &self.code[self.machine_st.p] {
+ &Instruction::BreakFromDispatchLoop => {
+ break 'outer;
+ }
+ &Instruction::InstallVerifyAttr => {
+ self.machine_st.p = self.machine_st.attr_var_init.p;
- match ct {
- &ClauseType::BuiltIn(ref ct) => {
- let ct = ct.clone();
+ if self.code[self.machine_st.p].is_execute() {
+ self.machine_st.p = self.machine_st.attr_var_init.cp;
+ } else {
+ self.machine_st.p += 1;
+ self.machine_st.cp = self.machine_st.attr_var_init.cp;
+ }
- try_or_fail!(
- self.machine_st,
- self.call_builtin(&ct)
- );
+ let mut p = self.machine_st.p;
- if !use_default_cp {
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- }
- &ClauseType::CallN => {
- try_or_fail!(
- self.machine_st,
- self.call_n(atom!("user"), arity)
- );
-
- if !use_default_cp {
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- }
- &ClauseType::Inlined(ref ct) => {
- let ct = ct.clone();
- self.execute_inlined(&ct);
+ while self.code[p].is_head_instr() {
+ p += 1;
+ }
- if lco {
- self.machine_st.p = CodePtr::Local(self.machine_st.cp);
- }
- }
- &ClauseType::Named(name, _, ref idx) => {
- let idx = idx.clone();
+ let instr = std::mem::replace(
+ &mut self.code[p],
+ Instruction::VerifyAttrInterrupt,
+ );
- try_or_fail!(
- self.machine_st,
- self.context_call(name, arity, idx) // TODO: change to idx.get() ???
- );
+ self.code[VERIFY_ATTR_INTERRUPT_LOC] = instr;
+ self.machine_st.attr_var_init.cp = p;
+ }
+ &Instruction::VerifyAttrInterrupt => {
+ self.run_verify_attr_interrupt();
+ }
+ &Instruction::Add(ref a1, ref a2, t) => {
+ let stub_gen = || functor_stub(atom!("is"), 2);
- if !use_default_cp {
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- }
- &ClauseType::System(ref ct) => {
- let ct = ct.clone();
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- try_or_fail!(
- self.machine_st,
- self.system_call(&ct)
- );
- }
- };
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ try_numeric_result!(add(n1, n2, &mut self.machine_st.arena), stub_gen)
+ );
- self.machine_st.last_call = false;
- }
- &ControlInstruction::Deallocate =>
- self.machine_st.deallocate(),
- &ControlInstruction::JmpBy(arity, offset, _, lco) => {
- if !lco {
- self.machine_st.cp.assign_if_local(self.machine_st.p.clone() + 1);
- }
+ self.machine_st.p += 1;
+ }
+ &Instruction::Sub(ref a1, ref a2, t) => {
+ let stub_gen = || functor_stub(atom!("is"), 2);
- self.machine_st.num_of_args = arity;
- self.machine_st.b0 = self.machine_st.b;
- self.machine_st.p += offset;
- }
- &ControlInstruction::RevJmpBy(offset) => {
- self.machine_st.p -= offset;
- }
- &ControlInstruction::Proceed => {
- self.machine_st.p = CodePtr::Local(self.machine_st.cp);
- }
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
+
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ try_numeric_result!(sub(n1, n2, &mut self.machine_st.arena), stub_gen)
+ );
+ self.machine_st.p += 1;
}
- }
- &Line::Fact(ref fact_instr) => {
- match fact_instr {
- &FactInstruction::GetConstant(_, c, reg) => {
- let value = self.machine_st.deref(self.machine_st[reg]);
- self.machine_st.write_literal_to_var(value, c);
- }
- &FactInstruction::GetList(_, reg) => {
- let deref_v = self.machine_st.deref(self.machine_st[reg]);
- let store_v = self.machine_st.store(deref_v);
-
- read_heap_cell!(store_v,
- (HeapCellValueTag::PStrLoc, h) => {
- let (h, n) = pstr_loc_and_offset(&self.machine_st.heap, h);
-
- self.machine_st.s = HeapPtr::PStrChar(h, n.get_num() as usize);
- self.machine_st.mode = MachineMode::Read;
- }
- (HeapCellValueTag::CStr) => {
- let h = self.machine_st.heap.len();
- self.machine_st.heap.push(store_v);
+ &Instruction::Mul(ref a1, ref a2, t) => {
+ let stub_gen = || functor_stub(atom!("is"), 2);
- self.machine_st.s = HeapPtr::PStrChar(h, 0);
- self.machine_st.mode = MachineMode::Read;
- }
- (HeapCellValueTag::Lis, l) => {
- self.machine_st.s = HeapPtr::HeapCell(l);
- self.machine_st.mode = MachineMode::Read;
- }
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
- let h = self.machine_st.heap.len();
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- self.machine_st.heap.push(list_loc_as_cell!(h+1));
- self.machine_st.bind(store_v.as_var().unwrap(), heap_loc_as_cell!(h));
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ try_numeric_result!(mul(n1, n2, &mut self.machine_st.arena), stub_gen)
+ );
- self.machine_st.mode = MachineMode::Write;
- }
- _ => {
- self.machine_st.fail = true;
- }
- );
- }
- &FactInstruction::GetPartialString(_, string, reg, has_tail) => {
- let deref_v = self.machine_st.deref(self.machine_st[reg]);
- let store_v = self.machine_st.store(deref_v);
+ self.machine_st.p += 1;
+ }
+ &Instruction::Max(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- read_heap_cell!(store_v,
- (HeapCellValueTag::Str | HeapCellValueTag::Lis |
- HeapCellValueTag::PStrLoc | HeapCellValueTag::AttrVar |
- HeapCellValueTag::StackVar | HeapCellValueTag::Var |
- HeapCellValueTag::CStr) => {
- self.machine_st.match_partial_string(store_v, string, has_tail);
- }
- _ => {
- self.machine_st.fail = true;
- }
- );
- }
- &FactInstruction::GetStructure(ref ct, arity, reg) => {
- let deref_v = self.machine_st.deref(self.machine_st[reg]);
- let store_v = self.machine_st.store(deref_v);
-
- read_heap_cell!(store_v,
- (HeapCellValueTag::Str, a) => {
- let result = self.machine_st.heap[a];
-
- read_heap_cell!(result,
- (HeapCellValueTag::Atom, (name, narity)) => {
- if narity == arity && ct.name() == name {
- self.machine_st.s = HeapPtr::HeapCell(a + 1);
- self.machine_st.mode = MachineMode::Read;
- } else {
- self.machine_st.fail = true;
- }
- }
- _ => {
- unreachable!();
- }
- );
- }
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
- let h = self.machine_st.heap.len();
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ max(n1, n2)
+ );
- self.machine_st.heap.push(str_loc_as_cell!(h+1));
- self.machine_st.heap.push(atom_as_cell!(ct.name(), arity));
+ self.machine_st.p += 1;
+ }
+ &Instruction::Min(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- self.machine_st.bind(store_v.as_var().unwrap(), heap_loc_as_cell!(h));
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ min(n1, n2)
+ );
- self.machine_st.mode = MachineMode::Write;
- }
- _ => {
- self.machine_st.fail = true;
- }
- );
- }
- &FactInstruction::GetVariable(norm, arg) => {
- self.machine_st[norm] = self.machine_st.registers[arg];
- }
- &FactInstruction::GetValue(norm, arg) => {
- let norm_addr = self.machine_st[norm];
- let reg_addr = self.machine_st.registers[arg];
+ self.machine_st.p += 1;
+ }
+ &Instruction::IntPow(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- unify_fn!(&mut self.machine_st, norm_addr, reg_addr);
- }
- &FactInstruction::UnifyConstant(v) => {
- match self.machine_st.mode {
- MachineMode::Read => {
- let addr = self.machine_st.read_s();
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ int_pow(n1, n2, &mut self.machine_st.arena)
+ );
- self.machine_st.write_literal_to_var(addr, v);
- self.machine_st.increment_s_ptr(1);
- }
- MachineMode::Write => {
- self.machine_st.heap.push(v);
- }
- };
- }
- &FactInstruction::UnifyVariable(reg) => {
- match self.machine_st.mode {
- MachineMode::Read => {
- self.machine_st[reg] = self.machine_st.read_s();
- self.machine_st.increment_s_ptr(1);
- }
- MachineMode::Write => {
- let h = self.machine_st.heap.len();
+ self.machine_st.p += 1;
+ }
+ &Instruction::Gcd(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- self.machine_st.heap.push(heap_loc_as_cell!(h));
- self.machine_st[reg] = heap_loc_as_cell!(h);
- }
- };
- }
- &FactInstruction::UnifyLocalValue(reg) => {
- match self.machine_st.mode {
- MachineMode::Read => {
- let reg_addr = self.machine_st[reg];
- let value = self.machine_st.read_s();
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ gcd(n1, n2, &mut self.machine_st.arena)
+ );
- unify_fn!(&mut self.machine_st, reg_addr, value);
- self.machine_st.increment_s_ptr(1);
- }
- MachineMode::Write => {
- let value = self.machine_st.store(self.machine_st.deref(self.machine_st[reg]));
- let h = self.machine_st.heap.len();
+ self.machine_st.p += 1;
+ }
+ &Instruction::Pow(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- read_heap_cell!(value,
- (HeapCellValueTag::Var | HeapCellValueTag::AttrVar, hc) => {
- let value = self.machine_st.heap[hc];
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ pow(n1, n2, atom!("**"))
+ );
- self.machine_st.heap.push(value);
- self.machine_st.increment_s_ptr(1);
- }
- _ => {
- self.machine_st.heap.push(heap_loc_as_cell!(h));
- (self.machine_st.bind_fn)(
- &mut self.machine_st,
- Ref::heap_cell(h),
- value,
- );
- }
- );
- }
- };
- }
- &FactInstruction::UnifyValue(reg) => {
- match self.machine_st.mode {
- MachineMode::Read => {
- let reg_addr = self.machine_st[reg];
- let value = self.machine_st.read_s();
+ self.machine_st.p += 1;
+ }
+ &Instruction::RDiv(ref a1, ref a2, t) => {
+ let stub_gen = || functor_stub(atom!("(rdiv)"), 2);
- unify_fn!(&mut self.machine_st, reg_addr, value);
- self.machine_st.increment_s_ptr(1);
- }
- MachineMode::Write => {
- let h = self.machine_st.heap.len();
- self.machine_st.heap.push(heap_loc_as_cell!(h));
+ let r1 = try_or_throw!(self.machine_st, self.machine_st.get_rational(a1, stub_gen));
+ let r2 = try_or_throw!(self.machine_st, self.machine_st.get_rational(a2, stub_gen));
- let addr = self.machine_st.store(self.machine_st[reg]);
- (self.machine_st.bind_fn)(&mut self.machine_st, Ref::heap_cell(h), addr);
+ self.machine_st.interms[t - 1] = Number::Rational(arena_alloc!(
+ try_or_throw_gen!(&mut self.machine_st, rdiv(r1, r2)),
+ self.machine_st.arena
+ ));
- // the former code of this match arm was:
+ self.machine_st.p += 1;
+ }
+ &Instruction::IntFloorDiv(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
+
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ int_floor_div(n1, n2, &mut self.machine_st.arena)
+ );
+ self.machine_st.p += 1;
+ }
+ &Instruction::IDiv(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
+
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ idiv(n1, n2, &mut self.machine_st.arena)
+ );
+ self.machine_st.p += 1;
+ }
+ &Instruction::Abs(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
- // let addr = self.machine_st.store(self.machine_st[reg]);
- // self.machine_st.heap.push(HeapCellValue::Addr(addr));
+ self.machine_st.interms[t - 1] = abs(n1, &mut self.machine_st.arena);
+ self.machine_st.p += 1;
+ }
+ &Instruction::Sign(ref a1, t) => {
+ let n = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
- // the old code didn't perform the occurs
- // check when enabled and so it was changed to
- // the above, which is only slightly less
- // efficient when the occurs_check is disabled.
- }
- };
- }
- &FactInstruction::UnifyVoid(n) => {
- match self.machine_st.mode {
- MachineMode::Read => {
- self.machine_st.increment_s_ptr(n);
- }
- MachineMode::Write => {
- let h = self.machine_st.heap.len();
+ self.machine_st.interms[t - 1] = sign(n);
+ self.machine_st.p += 1;
+ }
+ &Instruction::Neg(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
- for i in h..h + n {
- self.machine_st.heap.push(heap_loc_as_cell!(i));
- }
- }
- };
- }
+ self.machine_st.interms[t - 1] = neg(n1, &mut self.machine_st.arena);
+ self.machine_st.p += 1;
}
- self.machine_st.p += 1;
- }
- &Line::IndexingCode(ref indexing_lines) => {
- #[inline(always)]
- fn dynamic_external_of_clause_is_valid(machine: &mut Machine, p: usize) -> bool {
- match &machine.code_repo.code[p] {
- Line::Choice(ChoiceInstruction::DynamicInternalElse(..)) => {
- machine.machine_st.dynamic_mode = FirstOrNext::First;
- return true;
- }
- _ => {}
- }
+ &Instruction::BitwiseComplement(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
- match &machine.code_repo.code[p - 1] {
- &Line::Choice(ChoiceInstruction::DynamicInternalElse(birth, death, _)) => {
- if birth < machine.machine_st.cc && Death::Finite(machine.machine_st.cc) <= death {
- return true;
- } else {
- return false;
- }
- }
- _ => {}
- }
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ bitwise_complement(n1, &mut self.machine_st.arena)
+ );
- true
+ self.machine_st.p += 1;
}
+ &Instruction::Div(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- let mut index = 0;
- let addr = match &indexing_lines[0] {
- &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(arg, ..)) => {
- self.machine_st.store(self.machine_st.deref(self.machine_st.registers[arg]))
- }
- _ => {
- unreachable!()
- }
- };
-
- loop {
- match &indexing_lines[index] {
- &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, c, l, s)) => {
- let offset = read_heap_cell!(addr,
- (HeapCellValueTag::Var |
- HeapCellValueTag::StackVar |
- HeapCellValueTag::AttrVar) => {
- v
- }
- (HeapCellValueTag::PStrLoc |
- HeapCellValueTag::Lis |
- HeapCellValueTag::CStr) => {
- l
- }
- (HeapCellValueTag::Fixnum |
- HeapCellValueTag::Char |
- HeapCellValueTag::F64) => {
- c
- }
- (HeapCellValueTag::Atom, (_name, arity)) => {
- // if arity == 0 { c } else { s }
- debug_assert!(arity == 0);
- c
- }
- (HeapCellValueTag::Str) => {
- s
- }
- (HeapCellValueTag::Cons, ptr) => {
- match ptr.get_tag() {
- ArenaHeaderTag::Rational | ArenaHeaderTag::Integer |
- ArenaHeaderTag::F64 => {
- c
- }
- _ => {
- IndexingCodePtr::Fail
- }
- }
- }
- _ => {
- unreachable!();
- }
- );
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ div(n1, n2)
+ );
- match offset {
- IndexingCodePtr::Fail => {
- self.machine_st.fail = true;
- break;
- }
- IndexingCodePtr::DynamicExternal(o) => {
- // either points directly to a
- // DynamicInternalElse, or just ahead of
- // one. Or neither!
- let p = self.machine_st.p.local().abs_loc();
-
- if !dynamic_external_of_clause_is_valid(self, p + o) {
- self.machine_st.fail = true;
- } else {
- self.machine_st.p += o;
- }
+ self.machine_st.p += 1;
+ }
+ &Instruction::Shr(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- break;
- }
- IndexingCodePtr::External(o) => {
- self.machine_st.p += o;
- break;
- }
- IndexingCodePtr::Internal(o) => {
- index += o;
- }
- }
- }
- &IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref hm)) => {
- let lit = read_heap_cell!(addr,
- (HeapCellValueTag::Char, c) => {
- Literal::Char(c)
- }
- (HeapCellValueTag::Fixnum, n) => {
- Literal::Fixnum(n)
- }
- (HeapCellValueTag::F64, f) => {
- Literal::Float(f)
- }
- (HeapCellValueTag::Atom, (atom, arity)) => {
- debug_assert_eq!(arity, 0);
- Literal::Atom(atom)
- }
- (HeapCellValueTag::Cons, cons_ptr) => {
- match_untyped_arena_ptr!(cons_ptr,
- (ArenaHeaderTag::Rational, r) => {
- Literal::Rational(r)
- }
- (ArenaHeaderTag::F64, f) => {
- Literal::Float(F64Ptr(f))
- }
- (ArenaHeaderTag::Integer, n) => {
- Literal::Integer(n)
- }
- _ => {
- unreachable!()
- }
- )
- }
- _ => {
- unreachable!()
- }
- );
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ shr(n1, n2, &mut self.machine_st.arena)
+ );
- let offset = match hm.get(&lit) {
- Some(offset) => *offset,
- _ => IndexingCodePtr::Fail,
- };
+ self.machine_st.p += 1;
+ }
+ &Instruction::Shl(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- match offset {
- IndexingCodePtr::Fail => {
- self.machine_st.fail = true;
- break;
- }
- IndexingCodePtr::DynamicExternal(o) => {
- // either points directly to a
- // DynamicInternalElse, or just ahead of
- // one. Or neither!
- let p = self.machine_st.p.local().abs_loc();
-
- if !dynamic_external_of_clause_is_valid(self, p + o) {
- self.machine_st.fail = true;
- } else {
- self.machine_st.p += o;
- }
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ shl(n1, n2, &mut self.machine_st.arena)
+ );
- break;
- }
- IndexingCodePtr::External(o) => {
- self.machine_st.p += o;
- break;
- }
- IndexingCodePtr::Internal(o) => {
- index += o;
- }
- }
- }
- &IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref hm)) => {
- let offset = read_heap_cell!(addr,
- (HeapCellValueTag::Atom, (name, arity)) => {
- match hm.get(&(name, arity)) {
- Some(offset) => *offset,
- None => IndexingCodePtr::Fail,
- }
- }
- (HeapCellValueTag::Str, s) => {
- let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
- .get_name_and_arity();
+ self.machine_st.p += 1;
+ }
+ &Instruction::Xor(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- match hm.get(&(name, arity)) {
- Some(offset) => *offset,
- None => IndexingCodePtr::Fail,
- }
- }
- _ => {
- IndexingCodePtr::Fail
- }
- );
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ xor(n1, n2, &mut self.machine_st.arena)
+ );
- match offset {
- IndexingCodePtr::Fail => {
- self.machine_st.fail = true;
- break;
- }
- IndexingCodePtr::DynamicExternal(o) => {
- let p = self.machine_st.p.local().abs_loc();
+ self.machine_st.p += 1;
+ }
+ &Instruction::And(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- if !dynamic_external_of_clause_is_valid(self, p + o) {
- self.machine_st.fail = true;
- } else {
- self.machine_st.p += o;
- }
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ and(n1, n2, &mut self.machine_st.arena)
+ );
- break;
- }
- IndexingCodePtr::External(o) => {
- self.machine_st.p += o;
- break;
- }
- IndexingCodePtr::Internal(o) => {
- index += o;
- }
- }
- }
- &IndexingLine::IndexedChoice(_) => {
- if let LocalCodePtr::DirEntry(p) = self.machine_st.p.local() {
- self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
- self.machine_st.oip = index as u32;
- self.machine_st.iip = 0;
- } else {
- unreachable!()
- }
+ self.machine_st.p += 1;
+ }
+ &Instruction::Or(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- break;
- }
- &IndexingLine::DynamicIndexedChoice(_) => {
- self.machine_st.dynamic_mode = FirstOrNext::First;
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ or(n1, n2, &mut self.machine_st.arena)
+ );
- if let LocalCodePtr::DirEntry(p) = self.machine_st.p.local() {
- self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
- self.machine_st.oip = index as u32;
- self.machine_st.iip = 0;
- } else {
- unreachable!()
- }
+ self.machine_st.p += 1;
+ }
+ &Instruction::Mod(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- break;
- }
- }
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ modulus(n1, n2, &mut self.machine_st.arena)
+ );
+
+ self.machine_st.p += 1;
}
- }
- &Line::IndexedChoice(ref choice_instr) => {
- match choice_instr {
- &IndexedChoiceInstruction::Try(offset) => {
- self.machine_st.indexed_try(offset);
- }
- &IndexedChoiceInstruction::Retry(l) => {
- self.retry(l);
+ &Instruction::Rem(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- &IndexedChoiceInstruction::Trust(l) => {
- self.trust(l);
+ self.machine_st.interms[t - 1] = try_or_throw_gen!(
+ &mut self.machine_st,
+ remainder(n1, n2, &mut self.machine_st.arena)
+ );
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
+ self.machine_st.p += 1;
}
- }
- &Line::DynamicIndexedChoice(_) => self.execute_dynamic_indexed_choice_instr(),
- &Line::Query(ref query_instr) => {
- match query_instr {
- &QueryInstruction::GetVariable(norm, arg) => {
- self.machine_st[norm] = self.machine_st.registers[arg];
- }
- &QueryInstruction::PutConstant(_, c, reg) => {
- self.machine_st[reg] = c;
- }
- &QueryInstruction::PutList(_, reg) => {
- self.machine_st[reg] = list_loc_as_cell!(self.machine_st.heap.len());
- }
- &QueryInstruction::PutPartialString(_, string, reg, has_tail) => {
- let pstr_addr = if has_tail {
- if string != atom!("") {
- let h = self.machine_st.heap.len();
- self.machine_st.heap.push(string_as_pstr_cell!(string));
+ &Instruction::Cos(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
- // the tail will be pushed by the next
- // instruction, so don't push one here.
+ self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
+ try_or_throw_gen!(&mut self.machine_st, cos(n1))
+ ));
- pstr_loc_as_cell!(h)
- } else {
- empty_list_as_cell!()
- }
- } else {
- string_as_cstr_cell!(string)
- };
+ self.machine_st.p += 1;
+ }
+ &Instruction::Sin(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
- self.machine_st[reg] = pstr_addr;
- }
- &QueryInstruction::PutStructure(ref ct, arity, reg) => {
- let h = self.machine_st.heap.len();
+ self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
+ try_or_throw_gen!(&mut self.machine_st, sin(n1))
+ ));
- self.machine_st.heap.push(atom_as_cell!(ct.name(), arity));
- self.machine_st[reg] = str_loc_as_cell!(h);
- }
- &QueryInstruction::PutUnsafeValue(n, arg) => {
- let s = stack_loc!(AndFrame, self.machine_st.e, n);
- let addr = self.machine_st.store(self.machine_st.deref(stack_loc_as_cell!(s)));
+ self.machine_st.p += 1;
+ }
+ &Instruction::Tan(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
- if addr.is_protected(self.machine_st.e) {
- self.machine_st.registers[arg] = addr;
- } else {
- let h = self.machine_st.heap.len();
+ self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
+ try_or_throw_gen!(&mut self.machine_st, tan(n1))
+ ));
- self.machine_st.heap.push(heap_loc_as_cell!(h));
- (self.machine_st.bind_fn)(&mut self.machine_st, Ref::heap_cell(h), addr);
+ self.machine_st.p += 1;
+ }
+ &Instruction::Sqrt(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
- self.machine_st.registers[arg] = heap_loc_as_cell!(h);
- }
- }
- &QueryInstruction::PutValue(norm, arg) => {
- self.machine_st.registers[arg] = self.machine_st[norm];
- }
- &QueryInstruction::PutVariable(norm, arg) => {
- match norm {
- RegType::Perm(n) => {
- self.machine_st[norm] = stack_loc_as_cell!(AndFrame, self.machine_st.e, n);
- self.machine_st.registers[arg] = self.machine_st[norm];
- }
- RegType::Temp(_) => {
- let h = self.machine_st.heap.len();
- self.machine_st.heap.push(heap_loc_as_cell!(h));
+ self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
+ try_or_throw_gen!(&mut self.machine_st, sqrt(n1))
+ ));
- self.machine_st[norm] = heap_loc_as_cell!(h);
- self.machine_st.registers[arg] = heap_loc_as_cell!(h);
- }
- };
- }
- &QueryInstruction::SetConstant(c) => {
- self.machine_st.heap.push(c);
- }
- &QueryInstruction::SetLocalValue(reg) => {
- let addr = self.machine_st.deref(self.machine_st[reg]);
- let stored_v = self.machine_st.store(addr);
+ self.machine_st.p += 1;
+ }
+ &Instruction::Log(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
- if stored_v.is_stack_var() {
- let h = self.machine_st.heap.len();
- self.machine_st.heap.push(heap_loc_as_cell!(h));
- (self.machine_st.bind_fn)(&mut self.machine_st, Ref::heap_cell(h), stored_v);
- } else {
- self.machine_st.heap.push(stored_v);
- }
- }
- &QueryInstruction::SetVariable(reg) => {
- let h = self.machine_st.heap.len();
- self.machine_st.heap.push(heap_loc_as_cell!(h));
- self.machine_st[reg] = heap_loc_as_cell!(h);
- }
- &QueryInstruction::SetValue(reg) => {
- let heap_val = self.machine_st.store(self.machine_st[reg]);
- self.machine_st.heap.push(heap_val);
- }
- &QueryInstruction::SetVoid(n) => {
- let h = self.machine_st.heap.len();
+ self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
+ try_or_throw_gen!(&mut self.machine_st, log(n1))
+ ));
- for i in h..h + n {
- self.machine_st.heap.push(heap_loc_as_cell!(i));
- }
- }
+ self.machine_st.p += 1;
}
+ &Instruction::Exp(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
- self.machine_st.p += 1;
- }
+ self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
+ try_or_throw_gen!(&mut self.machine_st, exp(n1))
+ ));
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::ACos(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+
+ self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
+ try_or_throw_gen!(&mut self.machine_st, acos(n1))
+ ));
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::ASin(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+
+ self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
+ try_or_throw_gen!(&mut self.machine_st, asin(n1))
+ ));
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::ATan(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+
+ self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
+ try_or_throw_gen!(&mut self.machine_st, atan(n1))
+ ));
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::ATan2(ref a1, ref a2, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(a2));
+
+ self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
+ try_or_throw_gen!(&mut self.machine_st, atan2(n1, n2))
+ ));
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::Float(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+
+ self.machine_st.interms[t - 1] = Number::Float(OrderedFloat(
+ try_or_throw_gen!(&mut self.machine_st, float(n1))
+ ));
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::Truncate(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+
+ self.machine_st.interms[t - 1] = truncate(n1, &mut self.machine_st.arena);
+ self.machine_st.p += 1;
+ }
+ &Instruction::Round(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+
+ self.machine_st.interms[t - 1] =
+ try_or_throw_gen!(&mut self.machine_st, round(n1, &mut self.machine_st.arena));
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::Ceiling(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+
+ self.machine_st.interms[t - 1] = ceiling(n1, &mut self.machine_st.arena);
+ self.machine_st.p += 1;
+ }
+ &Instruction::Floor(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+
+ self.machine_st.interms[t - 1] = floor(n1, &mut self.machine_st.arena);
+ self.machine_st.p += 1;
+ }
+ &Instruction::Plus(ref a1, t) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(a1));
+
+ self.machine_st.interms[t - 1] = n1;
+ self.machine_st.p += 1;
+ }
+ &Instruction::DynamicElse(..) => {
+ if let FirstOrNext::First = self.machine_st.dynamic_mode {
+ self.machine_st.cc = self.machine_st.global_clock;
+ }
+
+ let p = self.machine_st.p;
+
+ match self.find_living_dynamic_else(p) {
+ Some((p, next_i)) => {
+ self.machine_st.p = p;
+
+ match self.machine_st.dynamic_mode {
+ FirstOrNext::First if next_i == 0 => {
+ self.machine_st.p += 1;
+ }
+ FirstOrNext::First => {
+ self.machine_st.cc = self.machine_st.global_clock;
+
+ match self.find_living_dynamic_else(p + next_i) {
+ Some(_) => {
+ self.machine_st.registers[self.machine_st.num_of_args + 1] =
+ fixnum_as_cell!(Fixnum::build_with(self.machine_st.cc as i64));
+
+ self.machine_st.num_of_args += 1;
+ self.machine_st.try_me_else(next_i);
+ self.machine_st.num_of_args -= 1;
+ }
+ None => {
+ self.machine_st.p += 1;
+ }
+ }
+ }
+ FirstOrNext::Next => {
+ let n = self.machine_st
+ .stack
+ .index_or_frame(self.machine_st.b)
+ .prelude
+ .univ_prelude
+ .num_cells;
+
+ self.machine_st.cc = cell_as_fixnum!(
+ self.machine_st.stack[stack_loc!(OrFrame, self.machine_st.b, n-1)]
+ ).get_num() as usize;
+
+ if next_i > 0 {
+ match self.find_living_dynamic_else(p + next_i) {
+ Some(_) => {
+ self.retry_me_else(next_i);
+
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ None => {
+ self.trust_me();
+
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ }
+ } else {
+ self.trust_me();
+
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ }
+ }
+ }
+ None => {
+ self.machine_st.fail = true;
+ }
+ }
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ continue;
+ }
+
+ self.machine_st.dynamic_mode = FirstOrNext::Next;
+ }
+ &Instruction::DynamicInternalElse(..) => {
+ let p = self.machine_st.p;
+
+ match self.find_living_dynamic_else(p) {
+ Some((p, next_i)) => {
+ self.machine_st.p = p;
+
+ match self.machine_st.dynamic_mode {
+ FirstOrNext::First if next_i == 0 => {
+ self.machine_st.p += 1;
+ }
+ FirstOrNext::First => {
+ match self.find_living_dynamic_else(p + next_i) {
+ Some(_) => {
+ self.machine_st.registers[self.machine_st.num_of_args + 1] =
+ fixnum_as_cell!(Fixnum::build_with(self.machine_st.cc as i64));
+
+ self.machine_st.num_of_args += 1;
+ self.machine_st.try_me_else(next_i);
+ self.machine_st.num_of_args -= 1;
+ }
+ None => {
+ self.machine_st.p += 1;
+ }
+ }
+ }
+ FirstOrNext::Next => {
+ let n = self.machine_st
+ .stack
+ .index_or_frame(self.machine_st.b)
+ .prelude
+ .univ_prelude
+ .num_cells;
+
+ self.machine_st.cc = cell_as_fixnum!(
+ self.machine_st.stack[stack_loc!(OrFrame, self.machine_st.b, n-1)]
+ ).get_num() as usize;
+
+ if next_i > 0 {
+ match self.find_living_dynamic_else(p + next_i) {
+ Some(_) => {
+ self.retry_me_else(next_i);
+
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ None => {
+ self.trust_me();
+
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ }
+ } else {
+ self.trust_me();
+
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ }
+ }
+ }
+ None => {
+ self.machine_st.fail = true;
+ }
+ }
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ continue;
+ }
+
+ self.machine_st.dynamic_mode = FirstOrNext::Next;
+ }
+ &Instruction::TryMeElse(offset) => {
+ self.machine_st.try_me_else(offset);
+ }
+ &Instruction::DefaultRetryMeElse(offset) => {
+ self.retry_me_else(offset);
+ }
+ &Instruction::DefaultTrustMe(_) => {
+ self.trust_me();
+ }
+ &Instruction::RetryMeElse(offset) => {
+ self.retry_me_else(offset);
+
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ &Instruction::TrustMe(_) => {
+ self.trust_me();
+
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ &Instruction::NeckCut => {
+ let b = self.machine_st.b;
+ let b0 = self.machine_st.b0;
+
+ if b > b0 {
+ self.machine_st.b = b0;
+
+ if b > self.machine_st.e {
+ self.machine_st.stack.truncate(b);
+ }
+ }
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::GetLevel(r) => {
+ let b0 = self.machine_st.b0;
+
+ self.machine_st[r] = fixnum_as_cell!(Fixnum::build_with(b0 as i64));
+ self.machine_st.p += 1;
+ }
+ &Instruction::GetLevelAndUnify(r) => {
+ // let b0 = self.machine_st[perm_v!(1)];
+ let b0 = cell_as_fixnum!(
+ self.machine_st.stack[stack_loc!(AndFrame, self.machine_st.e, 1)]
+ );
+ let a = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ // unify_fn!(&mut self.machine_st, a, b0);
+ self.machine_st.unify_fixnum(b0, a);
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::Cut(r) => {
+ let value = self.machine_st[r];
+ self.machine_st.cut_body(value);
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ continue;
+ }
+
+ if (self.machine_st.run_cleaners_fn)(self) {
+ continue;
+ }
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::Allocate(num_cells) => {
+ self.machine_st.allocate(num_cells);
+ }
+ &Instruction::DefaultCallAcyclicTerm(_) => {
+ let addr = self.machine_st.registers[1];
+
+ if self.machine_st.is_cyclic_term(addr) {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::DefaultExecuteAcyclicTerm(_) => {
+ let addr = self.machine_st.registers[1];
+
+ if self.machine_st.is_cyclic_term(addr) {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::DefaultCallArg(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.try_arg());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::DefaultExecuteArg(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.try_arg());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::DefaultCallCompare(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.compare());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::DefaultExecuteCompare(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.compare());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::DefaultCallTermGreaterThan(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2) {
+ self.machine_st.p += 1;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::DefaultExecuteTermGreaterThan(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2) {
+ self.machine_st.p = self.machine_st.cp;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::DefaultCallTermLessThan(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
+ self.machine_st.p += 1;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::DefaultExecuteTermLessThan(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
+ self.machine_st.p = self.machine_st.cp;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::DefaultCallTermGreaterThanOrEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ match compare_term_test!(self.machine_st, a1, a2) {
+ Some(Ordering::Greater | Ordering::Equal) => {
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultExecuteTermGreaterThanOrEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ match compare_term_test!(self.machine_st, a1, a2) {
+ Some(Ordering::Greater | Ordering::Equal) => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultCallTermLessThanOrEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ match compare_term_test!(self.machine_st, a1, a2) {
+ Some(Ordering::Less | Ordering::Equal) => {
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultExecuteTermLessThanOrEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ match compare_term_test!(self.machine_st, a1, a2) {
+ Some(Ordering::Less | Ordering::Equal) => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultCallRead(_) => {
+ try_or_throw!(self.machine_st, self.read());
+
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::DefaultExecuteRead(_) => {
+ try_or_throw!(self.machine_st, self.read());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::DefaultCallCopyTerm(_) => {
+ self.machine_st.copy_term(AttrVarPolicy::DeepCopy);
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::DefaultExecuteCopyTerm(_) => {
+ self.machine_st.copy_term(AttrVarPolicy::DeepCopy);
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::DefaultCallTermEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if self.machine_st.eq_test(a1, a2) {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::DefaultExecuteTermEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if self.machine_st.eq_test(a1, a2) {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::DefaultCallGround(_) => {
+ if self.machine_st.ground_test() {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::DefaultExecuteGround(_) => {
+ if self.machine_st.ground_test() {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::DefaultCallFunctor(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.try_functor());
+
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::DefaultExecuteFunctor(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.try_functor());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::DefaultCallTermNotEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::DefaultExecuteTermNotEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::DefaultCallSort(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.sort());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::DefaultExecuteSort(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.sort());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::DefaultCallKeySort(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.keysort());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::DefaultExecuteKeySort(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.keysort());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::DefaultCallIs(r, at, _) => {
+ try_or_throw!(self.machine_st, self.machine_st.is(r, at));
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::DefaultExecuteIs(r, at, _) => {
+ try_or_throw!(self.machine_st, self.machine_st.is(r, at));
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallAcyclicTerm(_) => {
+ let addr = self.machine_st.registers[1];
+
+ if self.machine_st.is_cyclic_term(addr) {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteAcyclicTerm(_) => {
+ let addr = self.machine_st.registers[1];
+
+ if self.machine_st.is_cyclic_term(addr) {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallArg(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.try_arg());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteArg(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.try_arg());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallCompare(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.compare());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteCompare(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.compare());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallTermGreaterThan(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2) {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::ExecuteTermGreaterThan(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if let Some(Ordering::Greater) = compare_term_test!(self.machine_st, a1, a2) {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::CallTermLessThan(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::ExecuteTermLessThan(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if let Some(Ordering::Less) = compare_term_test!(self.machine_st, a1, a2) {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::CallTermGreaterThanOrEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ match compare_term_test!(self.machine_st, a1, a2) {
+ Some(Ordering::Greater | Ordering::Equal) => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::ExecuteTermGreaterThanOrEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ match compare_term_test!(self.machine_st, a1, a2) {
+ Some(Ordering::Greater | Ordering::Equal) => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::CallTermLessThanOrEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ match compare_term_test!(self.machine_st, a1, a2) {
+ Some(Ordering::Less | Ordering::Equal) => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::ExecuteTermLessThanOrEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ match compare_term_test!(self.machine_st, a1, a2) {
+ Some(Ordering::Less | Ordering::Equal) => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::CallRead(_) => {
+ try_or_throw!(self.machine_st, self.read());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteRead(_) => {
+ try_or_throw!(self.machine_st, self.read());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallCopyTerm(_) => {
+ self.machine_st.copy_term(AttrVarPolicy::DeepCopy);
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteCopyTerm(_) => {
+ self.machine_st.copy_term(AttrVarPolicy::DeepCopy);
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallTermEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if self.machine_st.eq_test(a1, a2) {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteTermEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if self.machine_st.eq_test(a1, a2) {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallGround(_) => {
+ if self.machine_st.ground_test() {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteGround(_) => {
+ if self.machine_st.ground_test() {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallFunctor(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.try_functor());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteFunctor(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.try_functor());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallTermNotEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteTermNotEqual(_) => {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
+
+ if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallSort(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.sort());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteSort(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.sort());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallKeySort(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.keysort());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteKeySort(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.keysort());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallIs(r, at, _) => {
+ try_or_throw!(self.machine_st, self.machine_st.is(r, at));
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteIs(r, at, _) => {
+ try_or_throw!(self.machine_st, self.machine_st.is(r, at));
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallN(arity, _) => {
+ let pred = self.machine_st.registers[1];
+
+ for i in 2..arity + 1 {
+ self.machine_st.registers[i - 1] = self.machine_st.registers[i];
+ }
+
+ self.machine_st.registers[arity] = pred;
+
+ try_or_throw!(
+ self.machine_st,
+ self.call_n(atom!("user"), arity)
+ );
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ }
+ &Instruction::ExecuteN(arity, _) => {
+ let pred = self.machine_st.registers[1];
+
+ for i in 2..arity + 1 {
+ self.machine_st.registers[i - 1] = self.machine_st.registers[i];
+ }
+
+ self.machine_st.registers[arity] = pred;
+
+ try_or_throw!(
+ self.machine_st,
+ self.execute_n(atom!("user"), arity)
+ );
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ }
+ &Instruction::DefaultCallN(arity, _) => {
+ let pred = self.machine_st.registers[1];
+
+ for i in 2..arity + 1 {
+ self.machine_st.registers[i - 1] = self.machine_st.registers[i];
+ }
+
+ self.machine_st.registers[arity] = pred;
+
+ try_or_throw!(
+ self.machine_st,
+ self.call_n(atom!("user"), arity)
+ );
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::DefaultExecuteN(arity, _) => {
+ let pred = self.machine_st.registers[1];
+
+ for i in 2..arity + 1 {
+ self.machine_st.registers[i - 1] = self.machine_st.registers[i];
+ }
+
+ self.machine_st.registers[arity] = pred;
+
+ try_or_throw!(
+ self.machine_st,
+ self.execute_n(atom!("user"), arity)
+ );
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::CallNumberLessThanOrEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Less | Ordering::Equal => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::ExecuteNumberLessThanOrEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Less | Ordering::Equal => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::CallNumberEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Equal => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::ExecuteNumberEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Equal => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::CallNumberNotEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Equal => {
+ self.machine_st.backtrack();
+ }
+ _ => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ }
+ }
+ &Instruction::ExecuteNumberNotEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Equal => {
+ self.machine_st.backtrack();
+ }
+ _ => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ }
+ &Instruction::CallNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Greater | Ordering::Equal => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::ExecuteNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Greater | Ordering::Equal => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::CallNumberGreaterThan(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Greater => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::ExecuteNumberGreaterThan(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Greater => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::CallNumberLessThan(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Less => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::ExecuteNumberLessThan(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Less => {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultCallNumberLessThanOrEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Less | Ordering::Equal => {
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultExecuteNumberLessThanOrEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Less | Ordering::Equal => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultCallNumberNotEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Equal => {
+ self.machine_st.backtrack();
+ }
+ _ => {
+ self.machine_st.p += 1;
+ }
+ }
+ }
+ &Instruction::DefaultExecuteNumberNotEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Equal => {
+ self.machine_st.backtrack();
+ }
+ _ => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ }
+ &Instruction::DefaultCallNumberEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Equal => {
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultExecuteNumberEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Equal => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultCallNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Greater | Ordering::Equal => {
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultExecuteNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Greater | Ordering::Equal => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultCallNumberGreaterThan(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Greater => {
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultExecuteNumberGreaterThan(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Greater => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultCallNumberLessThan(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Less => {
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::DefaultExecuteNumberLessThan(ref at_1, ref at_2, _) => {
+ let n1 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_1));
+ let n2 = try_or_throw!(self.machine_st, self.machine_st.get_number(at_2));
+
+ match n1.cmp(&n2) {
+ Ordering::Less => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ //
+ &Instruction::CallIsAtom(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ read_heap_cell!(d,
+ (HeapCellValueTag::Atom, (_name, arity)) => {
+ if arity == 0 {
+ self.machine_st.p += 1;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ (HeapCellValueTag::Char) => {
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ );
+ }
+ &Instruction::ExecuteIsAtom(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ read_heap_cell!(d,
+ (HeapCellValueTag::Atom, (_name, arity)) => {
+ if arity == 0 {
+ self.machine_st.p = self.machine_st.cp;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ (HeapCellValueTag::Char) => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ );
+ }
+ &Instruction::CallIsAtomic(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ read_heap_cell!(d,
+ (HeapCellValueTag::Char | HeapCellValueTag::Fixnum | HeapCellValueTag::F64 |
+ HeapCellValueTag::Cons) => {
+ self.machine_st.p += 1;
+ }
+ (HeapCellValueTag::Atom, (_name, arity)) => {
+ if arity == 0 {
+ self.machine_st.p += 1;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ );
+ }
+ &Instruction::ExecuteIsAtomic(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ read_heap_cell!(d,
+ (HeapCellValueTag::Char | HeapCellValueTag::Fixnum | HeapCellValueTag::F64 |
+ HeapCellValueTag::Cons) => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ (HeapCellValueTag::Atom, (_name, arity)) => {
+ if arity == 0 {
+ self.machine_st.p = self.machine_st.cp;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ );
+ }
+ &Instruction::CallIsCompound(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ read_heap_cell!(d,
+ (HeapCellValueTag::Str | HeapCellValueTag::Lis |
+ HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => {
+ self.machine_st.p += 1;
+ }
+ (HeapCellValueTag::Atom, (_name, arity)) => {
+ if arity > 0 {
+ self.machine_st.p += 1;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ );
+ }
+ &Instruction::ExecuteIsCompound(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ read_heap_cell!(d,
+ (HeapCellValueTag::Str | HeapCellValueTag::Lis |
+ HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ (HeapCellValueTag::Atom, (_name, arity)) => {
+ if arity > 0 {
+ self.machine_st.p = self.machine_st.cp;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ );
+ }
+ &Instruction::CallIsInteger(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ match Number::try_from(d) {
+ Ok(Number::Fixnum(_) | Number::Integer(_)) => {
+ self.machine_st.p += 1;
+ }
+ Ok(Number::Rational(n)) => {
+ if n.denom() == &1 {
+ self.machine_st.p += 1;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::ExecuteIsInteger(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ match Number::try_from(d) {
+ Ok(Number::Fixnum(_) | Number::Integer(_)) => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ Ok(Number::Rational(n)) => {
+ if n.denom() == &1 {
+ self.machine_st.p = self.machine_st.cp;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::CallIsNumber(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ match Number::try_from(d) {
+ Ok(Number::Fixnum(_) | Number::Integer(_) | Number::Float(_)) => {
+ self.machine_st.p += 1;
+ }
+ Ok(Number::Rational(n)) => {
+ if n.denom() == &1 {
+ self.machine_st.p += 1;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::ExecuteIsNumber(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ match Number::try_from(d) {
+ Ok(Number::Fixnum(_) | Number::Integer(_) | Number::Float(_)) => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ Ok(Number::Rational(n)) => {
+ if n.denom() == &1 {
+ self.machine_st.p = self.machine_st.cp;
+ } else {
+ self.machine_st.backtrack();
+ }
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::CallIsRational(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ read_heap_cell!(d,
+ (HeapCellValueTag::Cons, ptr) => {
+ match_untyped_arena_ptr!(ptr,
+ (ArenaHeaderTag::Rational, _r) => {
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ );
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ );
+ }
+ &Instruction::ExecuteIsRational(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ read_heap_cell!(d,
+ (HeapCellValueTag::Cons, ptr) => {
+ match_untyped_arena_ptr!(ptr,
+ (ArenaHeaderTag::Rational, _r) => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ );
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ );
+ }
+ &Instruction::CallIsFloat(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ match Number::try_from(d) {
+ Ok(Number::Float(_)) => {
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::ExecuteIsFloat(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ match Number::try_from(d) {
+ Ok(Number::Float(_)) => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::CallIsNonVar(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ match d.get_tag() {
+ HeapCellValueTag::AttrVar |
+ HeapCellValueTag::Var |
+ HeapCellValueTag::StackVar => {
+ self.machine_st.backtrack();
+ }
+ _ => {
+ self.machine_st.p += 1;
+ }
+ }
+ }
+ &Instruction::ExecuteIsNonVar(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ match d.get_tag() {
+ HeapCellValueTag::AttrVar |
+ HeapCellValueTag::Var |
+ HeapCellValueTag::StackVar => {
+ self.machine_st.backtrack();
+ }
+ _ => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ }
+ &Instruction::CallIsVar(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ match d.get_tag() {
+ HeapCellValueTag::AttrVar |
+ HeapCellValueTag::Var |
+ HeapCellValueTag::StackVar => {
+ self.machine_st.p += 1;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::ExecuteIsVar(r, _) => {
+ let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+
+ match d.get_tag() {
+ HeapCellValueTag::AttrVar |
+ HeapCellValueTag::Var |
+ HeapCellValueTag::StackVar => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ }
+ }
+ }
+ &Instruction::CallNamed(arity, name, ref idx, _) => {
+ let idx = idx.get();
+
+ try_or_throw!(
+ self.machine_st,
+ self.try_call(name, arity, idx)
+ );
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ }
+ &Instruction::ExecuteNamed(arity, name, ref idx, _) => {
+ let idx = idx.get();
+
+ try_or_throw!(
+ self.machine_st,
+ self.try_execute(name, arity, idx)
+ );
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ }
+ &Instruction::DefaultCallNamed(arity, name, ref idx, _) => {
+ let idx = idx.get();
+
+ try_or_throw!(
+ self.machine_st,
+ self.try_call(name, arity, idx)
+ );
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::DefaultExecuteNamed(arity, name, ref idx, _) => {
+ let idx = idx.get();
+
+ try_or_throw!(
+ self.machine_st,
+ self.try_execute(name, arity, idx)
+ );
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::Deallocate => {
+ self.machine_st.deallocate()
+ }
+ &Instruction::JmpByCall(arity, offset, _) => {
+ self.machine_st.num_of_args = arity;
+ self.machine_st.b0 = self.machine_st.b;
+ self.machine_st.cp = self.machine_st.p + 1;
+ self.machine_st.p += offset;
+ }
+ &Instruction::JmpByExecute(arity, offset, _) => {
+ self.machine_st.num_of_args = arity;
+ self.machine_st.b0 = self.machine_st.b;
+ self.machine_st.p += offset;
+ }
+ &Instruction::RevJmpBy(offset) => {
+ self.machine_st.p -= offset;
+ }
+ &Instruction::Proceed => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::GetConstant(_, c, reg) => {
+ let value = self.machine_st.deref(self.machine_st[reg]);
+ self.machine_st.write_literal_to_var(value, c);
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::GetList(_, reg) => {
+ let deref_v = self.machine_st.deref(self.machine_st[reg]);
+ let store_v = self.machine_st.store(deref_v);
+
+ read_heap_cell!(store_v,
+ (HeapCellValueTag::PStrLoc, h) => {
+ let (h, n) = pstr_loc_and_offset(&self.machine_st.heap, h);
+
+ self.machine_st.s = HeapPtr::PStrChar(h, n.get_num() as usize);
+ self.machine_st.mode = MachineMode::Read;
+ }
+ (HeapCellValueTag::CStr) => {
+ let h = self.machine_st.heap.len();
+ self.machine_st.heap.push(store_v);
+
+ self.machine_st.s = HeapPtr::PStrChar(h, 0);
+ self.machine_st.mode = MachineMode::Read;
+ }
+ (HeapCellValueTag::Lis, l) => {
+ self.machine_st.s = HeapPtr::HeapCell(l);
+ self.machine_st.mode = MachineMode::Read;
+ }
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
+ let h = self.machine_st.heap.len();
+
+ self.machine_st.heap.push(list_loc_as_cell!(h+1));
+ self.machine_st.bind(store_v.as_var().unwrap(), heap_loc_as_cell!(h));
+
+ self.machine_st.mode = MachineMode::Write;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ continue;
+ }
+ );
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::GetPartialString(_, string, reg, has_tail) => {
+ let deref_v = self.machine_st.deref(self.machine_st[reg]);
+ let store_v = self.machine_st.store(deref_v);
+
+ read_heap_cell!(store_v,
+ (HeapCellValueTag::Str | HeapCellValueTag::Lis |
+ HeapCellValueTag::PStrLoc | HeapCellValueTag::AttrVar |
+ HeapCellValueTag::StackVar | HeapCellValueTag::Var |
+ HeapCellValueTag::CStr) => {
+ self.machine_st.match_partial_string(store_v, string, has_tail);
+ }
+ _ => {
+ self.machine_st.backtrack();
+ continue;
+ }
+ );
+
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::GetStructure(name, arity, reg) => {
+ let deref_v = self.machine_st.deref(self.machine_st[reg]);
+ let store_v = self.machine_st.store(deref_v);
+
+ read_heap_cell!(store_v,
+ (HeapCellValueTag::Str, a) => {
+ read_heap_cell!(self.machine_st.heap[a],
+ (HeapCellValueTag::Atom, (result_name, result_arity)) => {
+ if arity == result_arity && name == result_name {
+ self.machine_st.s = HeapPtr::HeapCell(a + 1);
+ self.machine_st.mode = MachineMode::Read;
+ } else {
+ self.machine_st.backtrack();
+ continue;
+ }
+ }
+ _ => {
+ unreachable!();
+ }
+ );
+ }
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
+ let h = self.machine_st.heap.len();
+
+ self.machine_st.heap.push(str_loc_as_cell!(h+1));
+ self.machine_st.heap.push(atom_as_cell!(name, arity));
+
+ self.machine_st.bind(store_v.as_var().unwrap(), heap_loc_as_cell!(h));
+ self.machine_st.mode = MachineMode::Write;
+ }
+ _ => {
+ self.machine_st.backtrack();
+ continue;
+ }
+ );
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::GetVariable(norm, arg) => {
+ self.machine_st[norm] = self.machine_st.registers[arg];
+ self.machine_st.p += 1;
+ }
+ &Instruction::GetValue(norm, arg) => {
+ let norm_addr = self.machine_st[norm];
+ let reg_addr = self.machine_st.registers[arg];
+
+ unify_fn!(&mut self.machine_st, norm_addr, reg_addr);
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ continue;
+ }
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::UnifyConstant(v) => {
+ match self.machine_st.mode {
+ MachineMode::Read => {
+ let addr = self.machine_st.read_s();
+
+ self.machine_st.write_literal_to_var(addr, v);
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ continue;
+ } else {
+ self.machine_st.increment_s_ptr(1);
+ }
+ }
+ MachineMode::Write => {
+ self.machine_st.heap.push(v);
+ }
+ }
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::UnifyLocalValue(reg) => {
+ match self.machine_st.mode {
+ MachineMode::Read => {
+ let reg_addr = self.machine_st[reg];
+ let value = self.machine_st.read_s();
+
+ unify_fn!(&mut self.machine_st, reg_addr, value);
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ continue;
+ } else {
+ self.machine_st.increment_s_ptr(1);
+ }
+ }
+ MachineMode::Write => {
+ let value = self.machine_st.store(self.machine_st.deref(self.machine_st[reg]));
+ let h = self.machine_st.heap.len();
+
+ read_heap_cell!(value,
+ (HeapCellValueTag::Var | HeapCellValueTag::AttrVar, hc) => {
+ let value = self.machine_st.heap[hc];
+
+ self.machine_st.heap.push(value);
+ self.machine_st.increment_s_ptr(1);
+ }
+ _ => {
+ self.machine_st.heap.push(heap_loc_as_cell!(h));
+ (self.machine_st.bind_fn)(
+ &mut self.machine_st,
+ Ref::heap_cell(h),
+ value,
+ );
+ }
+ );
+ }
+ }
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::UnifyVariable(reg) => {
+ match self.machine_st.mode {
+ MachineMode::Read => {
+ self.machine_st[reg] = self.machine_st.read_s();
+ self.machine_st.increment_s_ptr(1);
+ }
+ MachineMode::Write => {
+ let h = self.machine_st.heap.len();
+
+ self.machine_st.heap.push(heap_loc_as_cell!(h));
+ self.machine_st[reg] = heap_loc_as_cell!(h);
+ }
+ }
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::UnifyValue(reg) => {
+ match self.machine_st.mode {
+ MachineMode::Read => {
+ let reg_addr = self.machine_st[reg];
+ let value = self.machine_st.read_s();
+
+ unify_fn!(&mut self.machine_st, reg_addr, value);
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ continue;
+ } else {
+ self.machine_st.increment_s_ptr(1);
+ }
+ }
+ MachineMode::Write => {
+ let h = self.machine_st.heap.len();
+ self.machine_st.heap.push(heap_loc_as_cell!(h));
+
+ let addr = self.machine_st.store(self.machine_st[reg]);
+ (self.machine_st.bind_fn)(&mut self.machine_st, Ref::heap_cell(h), addr);
+
+ // the former code of this match arm was:
+
+ // let addr = self.machine_st.store(self.machine_st[reg]);
+ // self.machine_st.heap.push(HeapCellValue::Addr(addr));
+
+ // the old code didn't perform the occurs
+ // check when enabled and so it was changed to
+ // the above, which is only slightly less
+ // efficient when the occurs_check is disabled.
+ }
+ }
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::UnifyVoid(n) => {
+ match self.machine_st.mode {
+ MachineMode::Read => {
+ self.machine_st.increment_s_ptr(n);
+ }
+ MachineMode::Write => {
+ let h = self.machine_st.heap.len();
+
+ for i in h..h + n {
+ self.machine_st.heap.push(heap_loc_as_cell!(i));
+ }
+ }
+ }
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::IndexingCode(ref indexing_lines) => {
+ match &indexing_lines[self.machine_st.oip as usize] {
+ IndexingLine::Indexing(_) => {
+ self.execute_switch_on_term();
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ }
+ }
+ IndexingLine::IndexedChoice(ref indexed_choice) => {
+ match &indexed_choice[self.machine_st.iip as usize] {
+ &IndexedChoiceInstruction::Try(offset) => {
+ self.machine_st.indexed_try(offset);
+ }
+ &IndexedChoiceInstruction::Retry(l) => {
+ self.retry(l);
+
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ &IndexedChoiceInstruction::Trust(l) => {
+ self.trust(l);
+
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ }
+ }
+ IndexingLine::DynamicIndexedChoice(_) => {
+ let p = self.machine_st.p;
+
+ match self.find_living_dynamic(self.machine_st.oip, self.machine_st.iip) {
+ Some((offset, oi, ii, is_next_clause)) => {
+ self.machine_st.p = p;
+ self.machine_st.oip = oi;
+ self.machine_st.iip = ii;
+
+ match self.machine_st.dynamic_mode {
+ FirstOrNext::First if !is_next_clause => {
+ self.machine_st.p = p + offset;
+ }
+ FirstOrNext::First => {
+ // there's a leading DynamicElse that sets self.machine_st.cc.
+ // self.machine_st.cc = self.machine_st.global_clock;
+
+ // see that there is a following dynamic_else
+ // clause so we avoid generating a choice
+ // point in case there isn't.
+ match self.find_living_dynamic(oi, ii + 1) {
+ Some(_) => {
+ self.machine_st.registers[self.machine_st.num_of_args + 1] =
+ fixnum_as_cell!(Fixnum::build_with(self.machine_st.cc as i64));
+
+ self.machine_st.num_of_args += 2;
+ self.machine_st.indexed_try(offset);
+ self.machine_st.num_of_args -= 2;
+ }
+ None => {
+ self.machine_st.p = p + offset;
+ self.machine_st.oip = 0;
+ self.machine_st.iip = 0;
+ }
+ }
+ }
+ FirstOrNext::Next => {
+ let b = self.machine_st.b;
+ let n = self.machine_st
+ .stack
+ .index_or_frame(b)
+ .prelude
+ .univ_prelude
+ .num_cells;
+
+ self.machine_st.cc = cell_as_fixnum!(
+ self.machine_st.stack[stack_loc!(OrFrame, b, n-2)]
+ ).get_num() as usize;
+
+ if is_next_clause {
+ match self.find_living_dynamic(self.machine_st.oip, self.machine_st.iip) {
+ Some(_) => {
+ self.retry(offset);
+
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ None => {
+ self.trust(offset);
+
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ }
+ } else {
+ self.trust(offset);
+
+ try_or_throw!(
+ self.machine_st,
+ (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ );
+ }
+ }
+ }
+ }
+ None => {
+ self.machine_st.fail = true;
+ }
+ }
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.dynamic_mode = FirstOrNext::Next;
+ }
+ }
+ }
+ }
+ &Instruction::PutConstant(_, c, reg) => {
+ self.machine_st[reg] = c;
+ self.machine_st.p += 1;
+ }
+ &Instruction::PutList(_, reg) => {
+ self.machine_st[reg] = list_loc_as_cell!(self.machine_st.heap.len());
+ self.machine_st.p += 1;
+ }
+ &Instruction::PutPartialString(_, string, reg, has_tail) => {
+ let pstr_addr = if has_tail {
+ if string != atom!("") {
+ let h = self.machine_st.heap.len();
+ self.machine_st.heap.push(string_as_pstr_cell!(string));
+
+ // the tail will be pushed by the next
+ // instruction, so don't push one here.
+
+ pstr_loc_as_cell!(h)
+ } else {
+ empty_list_as_cell!()
+ }
+ } else {
+ string_as_cstr_cell!(string)
+ };
+
+ self.machine_st[reg] = pstr_addr;
+ self.machine_st.p += 1;
+ }
+ &Instruction::PutStructure(name, arity, reg) => {
+ let h = self.machine_st.heap.len();
+
+ self.machine_st.heap.push(atom_as_cell!(name, arity));
+ self.machine_st[reg] = str_loc_as_cell!(h);
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::PutUnsafeValue(n, arg) => {
+ let s = stack_loc!(AndFrame, self.machine_st.e, n);
+ let addr = self.machine_st.store(self.machine_st.deref(stack_loc_as_cell!(s)));
+
+ if addr.is_protected(self.machine_st.e) {
+ self.machine_st.registers[arg] = addr;
+ } else {
+ let h = self.machine_st.heap.len();
+
+ self.machine_st.heap.push(heap_loc_as_cell!(h));
+ (self.machine_st.bind_fn)(&mut self.machine_st, Ref::heap_cell(h), addr);
+
+ self.machine_st.registers[arg] = heap_loc_as_cell!(h);
+ }
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::PutValue(norm, arg) => {
+ self.machine_st.registers[arg] = self.machine_st[norm];
+ self.machine_st.p += 1;
+ }
+ &Instruction::PutVariable(norm, arg) => {
+ match norm {
+ RegType::Perm(n) => {
+ self.machine_st[norm] = stack_loc_as_cell!(AndFrame, self.machine_st.e, n);
+ self.machine_st.registers[arg] = self.machine_st[norm];
+ }
+ RegType::Temp(_) => {
+ let h = self.machine_st.heap.len();
+ self.machine_st.heap.push(heap_loc_as_cell!(h));
+
+ self.machine_st[norm] = heap_loc_as_cell!(h);
+ self.machine_st.registers[arg] = heap_loc_as_cell!(h);
+ }
+ };
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::SetConstant(c) => {
+ self.machine_st.heap.push(c);
+ self.machine_st.p += 1;
+ }
+ &Instruction::SetLocalValue(reg) => {
+ let addr = self.machine_st.deref(self.machine_st[reg]);
+ let stored_v = self.machine_st.store(addr);
+
+ if stored_v.is_stack_var() {
+ let h = self.machine_st.heap.len();
+ self.machine_st.heap.push(heap_loc_as_cell!(h));
+ (self.machine_st.bind_fn)(&mut self.machine_st, Ref::heap_cell(h), stored_v);
+ } else {
+ self.machine_st.heap.push(stored_v);
+ }
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::SetVariable(reg) => {
+ let h = self.machine_st.heap.len();
+
+ self.machine_st.heap.push(heap_loc_as_cell!(h));
+ self.machine_st[reg] = heap_loc_as_cell!(h);
+
+ self.machine_st.p += 1;
+ }
+ &Instruction::SetValue(reg) => {
+ let heap_val = self.machine_st.store(self.machine_st[reg]);
+ self.machine_st.heap.push(heap_val);
+ self.machine_st.p += 1;
+ }
+ &Instruction::SetVoid(n) => {
+ let h = self.machine_st.heap.len();
+
+ for i in h..h + n {
+ self.machine_st.heap.push(heap_loc_as_cell!(i));
+ }
+
+ self.machine_st.p += 1;
+ }
+ //
+ &Instruction::CallAtomChars(_) => {
+ self.atom_chars();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteAtomChars(_) => {
+ self.atom_chars();
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallAtomCodes(_) => {
+ try_or_throw!(self.machine_st, self.atom_codes());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteAtomCodes(_) => {
+ try_or_throw!(self.machine_st, self.atom_codes());
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ } else {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallAtomLength(_) => {
+ self.atom_length();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteAtomLength(_) => {
+ self.atom_length();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallBindFromRegister(_) => {
+ self.bind_from_register();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteBindFromRegister(_) => {
+ self.bind_from_register();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallContinuation(_) => {
+ try_or_throw!(self.machine_st, self.call_continuation(false));
+ }
+ &Instruction::ExecuteContinuation(_) => {
+ try_or_throw!(self.machine_st, self.call_continuation(true));
+ }
+ &Instruction::CallCharCode(_) => {
+ try_or_throw!(self.machine_st, self.char_code());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCharCode(_) => {
+ try_or_throw!(self.machine_st, self.char_code());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCharType(_) => {
+ self.char_type();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCharType(_) => {
+ self.char_type();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCharsToNumber(_) => {
+ try_or_throw!(self.machine_st, self.chars_to_number());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCharsToNumber(_) => {
+ try_or_throw!(self.machine_st, self.chars_to_number());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCodesToNumber(_) => {
+ try_or_throw!(self.machine_st, self.codes_to_number());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCodesToNumber(_) => {
+ try_or_throw!(self.machine_st, self.codes_to_number());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCopyTermWithoutAttrVars(_) => {
+ self.copy_term_without_attr_vars();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCopyTermWithoutAttrVars(_) => {
+ self.copy_term_without_attr_vars();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCheckCutPoint(_) => {
+ self.check_cut_point();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCheckCutPoint(_) => {
+ self.check_cut_point();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallClose(_) => {
+ try_or_throw!(self.machine_st, self.close());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteClose(_) => {
+ try_or_throw!(self.machine_st, self.close());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallCopyToLiftedHeap(_) => {
+ self.copy_to_lifted_heap();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteCopyToLiftedHeap(_) => {
+ self.copy_to_lifted_heap();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallCreatePartialString(_) => {
+ self.create_partial_string();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCreatePartialString(_) => {
+ self.create_partial_string();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCurrentHostname(_) => {
+ self.current_hostname();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCurrentHostname(_) => {
+ self.current_hostname();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCurrentInput(_) => {
+ try_or_throw!(self.machine_st, self.current_input());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCurrentInput(_) => {
+ try_or_throw!(self.machine_st, self.current_input());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCurrentOutput(_) => {
+ try_or_throw!(self.machine_st, self.current_output());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCurrentOutput(_) => {
+ try_or_throw!(self.machine_st, self.current_output());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallDirectoryFiles(_) => {
+ try_or_throw!(self.machine_st, self.directory_files());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteDirectoryFiles(_) => {
+ try_or_throw!(self.machine_st, self.directory_files());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallFileSize(_) => {
+ self.file_size();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteFileSize(_) => {
+ self.file_size();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallFileExists(_) => {
+ self.file_exists();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteFileExists(_) => {
+ self.file_exists();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallDirectoryExists(_) => {
+ self.directory_exists();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteDirectoryExists(_) => {
+ self.directory_exists();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallDirectorySeparator(_) => {
+ self.directory_separator();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteDirectorySeparator(_) => {
+ self.directory_separator();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallMakeDirectory(_) => {
+ self.make_directory();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteMakeDirectory(_) => {
+ self.make_directory();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallMakeDirectoryPath(_) => {
+ self.make_directory_path();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteMakeDirectoryPath(_) => {
+ self.make_directory_path();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallDeleteFile(_) => {
+ self.delete_file();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteDeleteFile(_) => {
+ self.delete_file();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallRenameFile(_) => {
+ self.rename_file();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteRenameFile(_) => {
+ self.rename_file();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallWorkingDirectory(_) => {
+ try_or_throw!(self.machine_st, self.working_directory());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteWorkingDirectory(_) => {
+ try_or_throw!(self.machine_st, self.working_directory());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallDeleteDirectory(_) => {
+ self.delete_directory();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteDeleteDirectory(_) => {
+ self.delete_directory();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallPathCanonical(_) => {
+ try_or_throw!(self.machine_st, self.path_canonical());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecutePathCanonical(_) => {
+ try_or_throw!(self.machine_st, self.path_canonical());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallFileTime(_) => {
+ self.file_time();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteFileTime(_) => {
+ self.file_time();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallDeleteAttribute(_) => {
+ self.delete_attribute();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteDeleteAttribute(_) => {
+ self.delete_attribute();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallDeleteHeadAttribute(_) => {
+ self.delete_head_attribute();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteDeleteHeadAttribute(_) => {
+ self.delete_head_attribute();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallDynamicModuleResolution(arity, _) => {
+ let (module_name, key) = try_or_throw!(
+ self.machine_st,
+ self.dynamic_module_resolution(arity - 2)
+ );
+
+ try_or_throw!(self.machine_st, self.call_clause(module_name, key));
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::ExecuteDynamicModuleResolution(arity, _) => {
+ let (module_name, key) = try_or_throw!(
+ self.machine_st,
+ self.dynamic_module_resolution(arity - 2)
+ );
+
+ try_or_throw!(self.machine_st, self.execute_clause(module_name, key));
+
+ if self.machine_st.fail {
+ self.machine_st.backtrack();
+ }
+ }
+ &Instruction::CallEnqueueAttributedVar(_) => {
+ self.enqueue_attributed_var();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteEnqueueAttributedVar(_) => {
+ self.enqueue_attributed_var();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallFetchGlobalVar(_) => {
+ self.fetch_global_var();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteFetchGlobalVar(_) => {
+ self.fetch_global_var();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallFirstStream(_) => {
+ self.first_stream();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteFirstStream(_) => {
+ self.first_stream();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallFlushOutput(_) => {
+ try_or_throw!(self.machine_st, self.flush_output());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteFlushOutput(_) => {
+ try_or_throw!(self.machine_st, self.flush_output());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallGetByte(_) => {
+ try_or_throw!(self.machine_st, self.get_byte());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetByte(_) => {
+ try_or_throw!(self.machine_st, self.get_byte());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetChar(_) => {
+ try_or_throw!(self.machine_st, self.get_char());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetChar(_) => {
+ try_or_throw!(self.machine_st, self.get_char());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetNChars(_) => {
+ try_or_throw!(self.machine_st, self.get_n_chars());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetNChars(_) => {
+ try_or_throw!(self.machine_st, self.get_n_chars());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetCode(_) => {
+ try_or_throw!(self.machine_st, self.get_code());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetCode(_) => {
+ try_or_throw!(self.machine_st, self.get_code());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetSingleChar(_) => {
+ try_or_throw!(self.machine_st, self.get_single_char());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetSingleChar(_) => {
+ try_or_throw!(self.machine_st, self.get_single_char());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallResetAttrVarState(_) => {
+ self.reset_attr_var_state();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteResetAttrVarState(_) => {
+ self.reset_attr_var_state();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallTruncateIfNoLiftedHeapGrowthDiff(_) => {
+ self.truncate_if_no_lifted_heap_growth_diff();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteTruncateIfNoLiftedHeapGrowthDiff(_) => {
+ self.truncate_if_no_lifted_heap_growth_diff();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallTruncateIfNoLiftedHeapGrowth(_) => {
+ self.truncate_if_no_lifted_heap_growth();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteTruncateIfNoLiftedHeapGrowth(_) => {
+ self.truncate_if_no_lifted_heap_growth();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetAttributedVariableList(_) => {
+ self.get_attributed_variable_list();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetAttributedVariableList(_) => {
+ self.get_attributed_variable_list();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetAttrVarQueueDelimiter(_) => {
+ self.get_attr_var_queue_delimiter();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetAttrVarQueueDelimiter(_) => {
+ self.get_attr_var_queue_delimiter();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetAttrVarQueueBeyond(_) => {
+ self.get_attr_var_queue_beyond();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetAttrVarQueueBeyond(_) => {
+ self.get_attr_var_queue_beyond();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetBValue(_) => {
+ self.get_b_value();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetBValue(_) => {
+ self.get_b_value();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetContinuationChunk(_) => {
+ self.get_continuation_chunk();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetContinuationChunk(_) => {
+ self.get_continuation_chunk();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetNextDBRef(_) => {
+ self.get_next_db_ref();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetNextDBRef(_) => {
+ self.get_next_db_ref();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetNextOpDBRef(_) => {
+ self.get_next_op_db_ref();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetNextOpDBRef(_) => {
+ self.get_next_op_db_ref();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallIsPartialString(_) => {
+ self.is_partial_string();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteIsPartialString(_) => {
+ self.is_partial_string();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallHalt(_) => {
+ self.halt();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteHalt(_) => {
+ self.halt();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallGetLiftedHeapFromOffset(_) => {
+ self.get_lifted_heap_from_offset();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetLiftedHeapFromOffset(_) => {
+ self.get_lifted_heap_from_offset();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetLiftedHeapFromOffsetDiff(_) => {
+ self.get_lifted_heap_from_offset_diff();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetLiftedHeapFromOffsetDiff(_) => {
+ self.get_lifted_heap_from_offset_diff();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetSCCCleaner(_) => {
+ self.get_scc_cleaner();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetSCCCleaner(_) => {
+ self.get_scc_cleaner();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallHeadIsDynamic(_) => {
+ self.head_is_dynamic();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteHeadIsDynamic(_) => {
+ self.head_is_dynamic();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallInstallSCCCleaner(_) => {
+ self.install_scc_cleaner();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteInstallSCCCleaner(_) => {
+ self.install_scc_cleaner();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallInstallInferenceCounter(_) => {
+ try_or_throw!(self.machine_st, self.install_inference_counter());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteInstallInferenceCounter(_) => {
+ try_or_throw!(self.machine_st, self.install_inference_counter());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallLiftedHeapLength(_) => {
+ self.lifted_heap_length();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteLiftedHeapLength(_) => {
+ self.lifted_heap_length();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallLoadLibraryAsStream(_) => {
+ try_or_throw!(self.machine_st, self.load_library_as_stream());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteLoadLibraryAsStream(_) => {
+ try_or_throw!(self.machine_st, self.load_library_as_stream());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallModuleExists(_) => {
+ self.module_exists();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteModuleExists(_) => {
+ self.module_exists();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallNextEP(_) => {
+ self.next_ep();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteNextEP(_) => {
+ self.next_ep();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallNoSuchPredicate(_) => {
+ try_or_throw!(self.machine_st, self.no_such_predicate());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteNoSuchPredicate(_) => {
+ try_or_throw!(self.machine_st, self.no_such_predicate());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallNumberToChars(_) => {
+ self.number_to_chars();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteNumberToChars(_) => {
+ self.number_to_chars();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallNumberToCodes(_) => {
+ self.number_to_codes();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteNumberToCodes(_) => {
+ self.number_to_codes();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallOpDeclaration(_) => {
+ try_or_throw!(self.machine_st, self.op_declaration());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteOpDeclaration(_) => {
+ try_or_throw!(self.machine_st, self.op_declaration());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallOpen(_) => {
+ try_or_throw!(self.machine_st, self.open());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteOpen(_) => {
+ try_or_throw!(self.machine_st, self.open());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallSetStreamOptions(_) => {
+ try_or_throw!(self.machine_st, self.set_stream_options());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteSetStreamOptions(_) => {
+ try_or_throw!(self.machine_st, self.set_stream_options());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallNextStream(_) => {
+ self.next_stream();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteNextStream(_) => {
+ self.next_stream();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallPartialStringTail(_) => {
+ self.partial_string_tail();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecutePartialStringTail(_) => {
+ self.partial_string_tail();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallPeekByte(_) => {
+ try_or_throw!(self.machine_st, self.peek_byte());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecutePeekByte(_) => {
+ try_or_throw!(self.machine_st, self.peek_byte());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallPeekChar(_) => {
+ try_or_throw!(self.machine_st, self.peek_char());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecutePeekChar(_) => {
+ try_or_throw!(self.machine_st, self.peek_char());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallPeekCode(_) => {
+ try_or_throw!(self.machine_st, self.peek_code());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecutePeekCode(_) => {
+ try_or_throw!(self.machine_st, self.peek_code());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallPointsToContinuationResetMarker(_) => {
+ self.points_to_continuation_reset_marker();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecutePointsToContinuationResetMarker(_) => {
+ self.points_to_continuation_reset_marker();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallPutByte(_) => {
+ try_or_throw!(self.machine_st, self.put_byte());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecutePutByte(_) => {
+ try_or_throw!(self.machine_st, self.put_byte());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallPutChar(_) => {
+ try_or_throw!(self.machine_st, self.put_char());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecutePutChar(_) => {
+ try_or_throw!(self.machine_st, self.put_char());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallPutChars(_) => {
+ try_or_throw!(self.machine_st, self.put_chars());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecutePutChars(_) => {
+ try_or_throw!(self.machine_st, self.put_chars());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallPutCode(_) => {
+ try_or_throw!(self.machine_st, self.put_code());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecutePutCode(_) => {
+ try_or_throw!(self.machine_st, self.put_code());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallReadQueryTerm(_) => {
+ try_or_throw!(self.machine_st, self.read_query_term());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteReadQueryTerm(_) => {
+ try_or_throw!(self.machine_st, self.read_query_term());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallReadTerm(_) => {
+ try_or_throw!(self.machine_st, self.read_term());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteReadTerm(_) => {
+ try_or_throw!(self.machine_st, self.read_term());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallRedoAttrVarBinding(_) => {
+ self.redo_attr_var_binding();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteRedoAttrVarBinding(_) => {
+ self.redo_attr_var_binding();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallRemoveCallPolicyCheck(_) => {
+ self.remove_call_policy_check();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteRemoveCallPolicyCheck(_) => {
+ self.remove_call_policy_check();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallRemoveInferenceCounter(_) => {
+ self.remove_inference_counter();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteRemoveInferenceCounter(_) => {
+ self.remove_inference_counter();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallResetContinuationMarker(_) => {
+ self.reset_continuation_marker();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteResetContinuationMarker(_) => {
+ self.reset_continuation_marker();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallRestoreCutPolicy(_) => {
+ self.restore_cut_policy();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteRestoreCutPolicy(_) => {
+ self.restore_cut_policy();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallSetCutPoint(r, _) => {
+ if !self.set_cut_point(r) {
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ }
+ &Instruction::ExecuteSetCutPoint(r, _) => {
+ let cp = self.machine_st.cp;
+
+ if !self.set_cut_point(r) {
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ } else {
+ // run_cleaners in set_cut_point calls call_by_index.
+ // replace the effect of call_by_index with that
+ // of execute_by_index here.
+
+ self.machine_st.cp = cp;
+ }
+ }
+ &Instruction::CallSetInput(_) => {
+ try_or_throw!(self.machine_st, self.set_input());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteSetInput(_) => {
+ try_or_throw!(self.machine_st, self.set_input());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallSetOutput(_) => {
+ try_or_throw!(self.machine_st, self.set_output());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteSetOutput(_) => {
+ try_or_throw!(self.machine_st, self.set_output());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallStoreBacktrackableGlobalVar(_) => {
+ self.store_backtrackable_global_var();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteStoreBacktrackableGlobalVar(_) => {
+ self.store_backtrackable_global_var();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallStoreGlobalVar(_) => {
+ self.store_global_var();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteStoreGlobalVar(_) => {
+ self.store_global_var();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallStreamProperty(_) => {
+ try_or_throw!(self.machine_st, self.stream_property());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteStreamProperty(_) => {
+ try_or_throw!(self.machine_st, self.stream_property());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallSetStreamPosition(_) => {
+ try_or_throw!(self.machine_st, self.set_stream_position());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteSetStreamPosition(_) => {
+ try_or_throw!(self.machine_st, self.set_stream_position());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallInferenceLevel(_) => {
+ self.inference_level();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteInferenceLevel(_) => {
+ self.inference_level();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCleanUpBlock(_) => {
+ self.clean_up_block();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteCleanUpBlock(_) => {
+ self.clean_up_block();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallEraseBall(_) => {
+ self.erase_ball();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteEraseBall(_) => {
+ self.erase_ball();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallFail(_) | &Instruction::ExecuteFail(_) => {
+ self.machine_st.backtrack();
+ }
+ &Instruction::CallGetBall(_) => {
+ self.get_ball();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetBall(_) => {
+ self.get_ball();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetCurrentBlock(_) => {
+ self.get_current_block();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetCurrentBlock(_) => {
+ self.get_current_block();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetCutPoint(_) => {
+ self.get_cut_point();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetCutPoint(_) => {
+ self.get_cut_point();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetStaggeredCutPoint(_) => {
+ self.get_staggered_cut_point();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetStaggeredCutPoint(_) => {
+ self.get_staggered_cut_point();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetDoubleQuotes(_) => {
+ self.get_double_quotes();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetDoubleQuotes(_) => {
+ self.get_double_quotes();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallInstallNewBlock(_) => {
+ self.machine_st.install_new_block(self.machine_st.registers[1]);
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteInstallNewBlock(_) => {
+ self.machine_st.install_new_block(self.machine_st.registers[1]);
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallMaybe(_) => {
+ self.maybe();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteMaybe(_) => {
+ self.maybe();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCpuNow(_) => {
+ self.cpu_now();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCpuNow(_) => {
+ self.cpu_now();
+ 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);
+ }
+ &Instruction::ExecuteCurrentTime(_) => {
+ self.current_time();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallQuotedToken(_) => {
+ self.quoted_token();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteQuotedToken(_) => {
+ self.quoted_token();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallReadTermFromChars(_) => {
+ try_or_throw!(self.machine_st, self.read_term_from_chars());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteReadTermFromChars(_) => {
+ try_or_throw!(self.machine_st, self.read_term_from_chars());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallResetBlock(_) => {
+ self.reset_block();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteResetBlock(_) => {
+ self.reset_block();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallReturnFromVerifyAttr(_) |
+ &Instruction::ExecuteReturnFromVerifyAttr(_) => {
+ self.return_from_verify_attr();
+ }
+ &Instruction::CallSetBall(_) => {
+ self.set_ball();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteSetBall(_) => {
+ self.set_ball();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallSetCutPointByDefault(r, _) => {
+ self.set_cut_point_by_default(r);
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteSetCutPointByDefault(r, _) => {
+ self.set_cut_point_by_default(r);
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallSetDoubleQuotes(_) => {
+ self.set_double_quotes();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteSetDoubleQuotes(_) => {
+ self.set_double_quotes();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallSetSeed(_) => {
+ self.set_seed();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteSetSeed(_) => {
+ self.set_seed();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallSkipMaxList(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.skip_max_list());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteSkipMaxList(_) => {
+ try_or_throw!(self.machine_st, self.machine_st.skip_max_list());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallSleep(_) => {
+ self.sleep();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteSleep(_) => {
+ self.sleep();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallSocketClientOpen(_) => {
+ try_or_throw!(self.machine_st, self.socket_client_open());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteSocketClientOpen(_) => {
+ try_or_throw!(self.machine_st, self.socket_client_open());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallSocketServerOpen(_) => {
+ try_or_throw!(self.machine_st, self.socket_server_open());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteSocketServerOpen(_) => {
+ try_or_throw!(self.machine_st, self.socket_server_open());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallSocketServerAccept(_) => {
+ try_or_throw!(self.machine_st, self.socket_server_accept());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteSocketServerAccept(_) => {
+ try_or_throw!(self.machine_st, self.socket_server_accept());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallSocketServerClose(_) => {
+ try_or_throw!(self.machine_st, self.socket_server_close());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteSocketServerClose(_) => {
+ try_or_throw!(self.machine_st, self.socket_server_close());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallTLSAcceptClient(_) => {
+ try_or_throw!(self.machine_st, self.tls_accept_client());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteTLSAcceptClient(_) => {
+ try_or_throw!(self.machine_st, self.tls_accept_client());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallTLSClientConnect(_) => {
+ try_or_throw!(self.machine_st, self.tls_client_connect());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteTLSClientConnect(_) => {
+ try_or_throw!(self.machine_st, self.tls_client_connect());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallSucceed(_) => {
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteSucceed(_) => {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallTermAttributedVariables(_) => {
+ self.term_attributed_variables();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteTermAttributedVariables(_) => {
+ self.term_attributed_variables();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallTermVariables(_) => {
+ self.term_variables();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteTermVariables(_) => {
+ self.term_variables();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallTermVariablesUnderMaxDepth(_) => {
+ self.term_variables_under_max_depth();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteTermVariablesUnderMaxDepth(_) => {
+ self.term_variables_under_max_depth();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallTruncateLiftedHeapTo(_) => {
+ self.truncate_lifted_heap_to();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteTruncateLiftedHeapTo(_) => {
+ self.truncate_lifted_heap_to();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallUnifyWithOccursCheck(_) => {
+ self.unify_with_occurs_check();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteUnifyWithOccursCheck(_) => {
+ self.unify_with_occurs_check();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallUnwindEnvironments(_) => {
+ if !self.unwind_environments() {
+ self.machine_st.p += 1;
+ }
+ }
+ &Instruction::ExecuteUnwindEnvironments(_) => {
+ if !self.unwind_environments() {
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ &Instruction::CallUnwindStack(_) | &Instruction::ExecuteUnwindStack(_) => {
+ self.machine_st.unwind_stack();
+ self.machine_st.backtrack();
+ }
+ &Instruction::CallWAMInstructions(_) => {
+ try_or_throw!(self.machine_st, self.wam_instructions());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteWAMInstructions(_) => {
+ try_or_throw!(self.machine_st, self.wam_instructions());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallWriteTerm(_) => {
+ try_or_throw!(self.machine_st, self.write_term());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteWriteTerm(_) => {
+ try_or_throw!(self.machine_st, self.write_term());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallWriteTermToChars(_) => {
+ try_or_throw!(self.machine_st, self.write_term_to_chars());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteWriteTermToChars(_) => {
+ try_or_throw!(self.machine_st, self.write_term_to_chars());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallScryerPrologVersion(_) => {
+ self.scryer_prolog_version();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteScryerPrologVersion(_) => {
+ self.scryer_prolog_version();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCryptoRandomByte(_) => {
+ self.crypto_random_byte();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCryptoRandomByte(_) => {
+ self.crypto_random_byte();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCryptoDataHash(_) => {
+ self.crypto_data_hash();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCryptoDataHash(_) => {
+ self.crypto_data_hash();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCryptoDataHKDF(_) => {
+ self.crypto_data_hkdf();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCryptoDataHKDF(_) => {
+ self.crypto_data_hkdf();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCryptoPasswordHash(_) => {
+ self.crypto_password_hash();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCryptoPasswordHash(_) => {
+ self.crypto_password_hash();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCryptoDataEncrypt(_) => {
+ self.crypto_data_encrypt();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCryptoDataEncrypt(_) => {
+ self.crypto_data_encrypt();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCryptoDataDecrypt(_) => {
+ self.crypto_data_decrypt();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCryptoDataDecrypt(_) => {
+ self.crypto_data_decrypt();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCryptoCurveScalarMult(_) => {
+ self.crypto_curve_scalar_mult();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCryptoCurveScalarMult(_) => {
+ self.crypto_curve_scalar_mult();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallEd25519Sign(_) => {
+ self.ed25519_sign();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteEd25519Sign(_) => {
+ self.ed25519_sign();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallEd25519Verify(_) => {
+ self.ed25519_verify();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteEd25519Verify(_) => {
+ self.ed25519_verify();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallEd25519NewKeyPair(_) => {
+ self.ed25519_new_key_pair();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteEd25519NewKeyPair(_) => {
+ self.ed25519_new_key_pair();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallEd25519KeyPairPublicKey(_) => {
+ self.ed25519_key_pair_public_key();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteEd25519KeyPairPublicKey(_) => {
+ self.ed25519_key_pair_public_key();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCurve25519ScalarMult(_) => {
+ self.curve25519_scalar_mult();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCurve25519ScalarMult(_) => {
+ self.curve25519_scalar_mult();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallFirstNonOctet(_) => {
+ self.first_non_octet();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteFirstNonOctet(_) => {
+ self.first_non_octet();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallLoadHTML(_) => {
+ self.load_html();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteLoadHTML(_) => {
+ self.load_html();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallLoadXML(_) => {
+ self.load_xml();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteLoadXML(_) => {
+ self.load_xml();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallGetEnv(_) => {
+ self.get_env();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteGetEnv(_) => {
+ self.get_env();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallSetEnv(_) => {
+ self.set_env();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteSetEnv(_) => {
+ self.set_env();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallUnsetEnv(_) => {
+ self.unset_env();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteUnsetEnv(_) => {
+ self.unset_env();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallShell(_) => {
+ self.shell();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteShell(_) => {
+ self.shell();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallPID(_) => {
+ self.pid();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecutePID(_) => {
+ self.pid();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallCharsBase64(_) => {
+ try_or_throw!(self.machine_st, self.chars_base64());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteCharsBase64(_) => {
+ try_or_throw!(self.machine_st, self.chars_base64());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallDevourWhitespace(_) => {
+ try_or_throw!(self.machine_st, self.devour_whitespace());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteDevourWhitespace(_) => {
+ try_or_throw!(self.machine_st, self.devour_whitespace());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallIsSTOEnabled(_) => {
+ self.is_sto_enabled();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteIsSTOEnabled(_) => {
+ self.is_sto_enabled();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallSetSTOAsUnify(_) => {
+ self.set_sto_as_unify();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteSetSTOAsUnify(_) => {
+ self.set_sto_as_unify();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallSetNSTOAsUnify(_) => {
+ self.set_nsto_as_unify();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteSetNSTOAsUnify(_) => {
+ self.set_nsto_as_unify();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallSetSTOWithErrorAsUnify(_) => {
+ self.set_sto_with_error_as_unify();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteSetSTOWithErrorAsUnify(_) => {
+ self.set_sto_with_error_as_unify();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallHomeDirectory(_) => {
+ self.home_directory();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteHomeDirectory(_) => {
+ self.home_directory();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallDebugHook(_) => {
+ self.debug_hook();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteDebugHook(_) => {
+ self.debug_hook();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallPopCount(_) => {
+ self.pop_count();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecutePopCount(_) => {
+ self.pop_count();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallAddDiscontiguousPredicate(_) => {
+ try_or_throw!(self.machine_st, self.add_discontiguous_predicate());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteAddDiscontiguousPredicate(_) => {
+ try_or_throw!(self.machine_st, self.add_discontiguous_predicate());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallAddDynamicPredicate(_) => {
+ try_or_throw!(self.machine_st, self.add_dynamic_predicate());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteAddDynamicPredicate(_) => {
+ try_or_throw!(self.machine_st, self.add_dynamic_predicate());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallAddMultifilePredicate(_) => {
+ try_or_throw!(self.machine_st, self.add_multifile_predicate());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteAddMultifilePredicate(_) => {
+ try_or_throw!(self.machine_st, self.add_multifile_predicate());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallAddGoalExpansionClause(_) => {
+ try_or_throw!(self.machine_st, self.add_goal_expansion_clause());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteAddGoalExpansionClause(_) => {
+ try_or_throw!(self.machine_st, self.add_goal_expansion_clause());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallAddTermExpansionClause(_) => {
+ try_or_throw!(self.machine_st, self.add_term_expansion_clause());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteAddTermExpansionClause(_) => {
+ try_or_throw!(self.machine_st, self.add_term_expansion_clause());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallAddInSituFilenameModule(_) => {
+ try_or_throw!(self.machine_st, self.add_in_situ_filename_module());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteAddInSituFilenameModule(_) => {
+ try_or_throw!(self.machine_st, self.add_in_situ_filename_module());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallClauseToEvacuable(_) => {
+ try_or_throw!(self.machine_st, self.clause_to_evacuable());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteClauseToEvacuable(_) => {
+ try_or_throw!(self.machine_st, self.clause_to_evacuable());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallScopedClauseToEvacuable(_) => {
+ try_or_throw!(self.machine_st, self.scoped_clause_to_evacuable());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteScopedClauseToEvacuable(_) => {
+ try_or_throw!(self.machine_st, self.scoped_clause_to_evacuable());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallConcludeLoad(_) => {
+ try_or_throw!(self.machine_st, self.conclude_load());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteConcludeLoad(_) => {
+ try_or_throw!(self.machine_st, self.conclude_load());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallDeclareModule(_) => {
+ try_or_throw!(self.machine_st, self.declare_module());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteDeclareModule(_) => {
+ try_or_throw!(self.machine_st, self.declare_module());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallLoadCompiledLibrary(_) => {
+ try_or_throw!(self.machine_st, self.load_compiled_library());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteLoadCompiledLibrary(_) => {
+ try_or_throw!(self.machine_st, self.load_compiled_library());
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallLoadContextSource(_) => {
+ self.load_context_source();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteLoadContextSource(_) => {
+ self.load_context_source();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallLoadContextFile(_) => {
+ self.load_context_file();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteLoadContextFile(_) => {
+ self.load_context_file();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallLoadContextDirectory(_) => {
+ self.load_context_directory();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteLoadContextDirectory(_) => {
+ self.load_context_directory();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallLoadContextModule(_) => {
+ self.load_context_module();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteLoadContextModule(_) => {
+ self.load_context_module();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallLoadContextStream(_) => {
+ self.load_context_stream();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteLoadContextStream(_) => {
+ self.load_context_stream();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallPopLoadContext(_) => {
+ self.pop_load_context();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecutePopLoadContext(_) => {
+ self.pop_load_context();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallPopLoadStatePayload(_) => {
+ self.pop_load_state_payload();
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecutePopLoadStatePayload(_) => {
+ self.pop_load_state_payload();
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallPushLoadContext(_) => {
+ try_or_throw!(self.machine_st, self.push_load_context());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecutePushLoadContext(_) => {
+ try_or_throw!(self.machine_st, self.push_load_context());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallPushLoadStatePayload(_) => {
+ self.push_load_state_payload();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecutePushLoadStatePayload(_) => {
+ self.push_load_state_payload();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallUseModule(_) => {
+ try_or_throw!(self.machine_st, self.use_module());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteUseModule(_) => {
+ try_or_throw!(self.machine_st, self.use_module());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallBuiltInProperty(_) => {
+ self.builtin_property();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteBuiltInProperty(_) => {
+ self.builtin_property();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallMetaPredicateProperty(_) => {
+ self.meta_predicate_property();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteMetaPredicateProperty(_) => {
+ self.meta_predicate_property();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallMultifileProperty(_) => {
+ self.multifile_property();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteMultifileProperty(_) => {
+ self.multifile_property();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallDiscontiguousProperty(_) => {
+ self.discontiguous_property();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteDiscontiguousProperty(_) => {
+ self.discontiguous_property();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallDynamicProperty(_) => {
+ self.dynamic_property();
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteDynamicProperty(_) => {
+ self.dynamic_property();
+ step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+ }
+ &Instruction::CallAbolishClause(_) => {
+ try_or_throw!(self.machine_st, self.abolish_clause());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteAbolishClause(_) => {
+ try_or_throw!(self.machine_st, self.abolish_clause());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallAsserta(_) => {
+ try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Prepend));
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteAsserta(_) => {
+ try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Prepend));
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallAssertz(_) => {
+ try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Append));
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteAssertz(_) => {
+ try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Append));
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallRetract(_) => {
+ try_or_throw!(self.machine_st, self.retract_clause());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteRetract(_) => {
+ try_or_throw!(self.machine_st, self.retract_clause());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallIsConsistentWithTermQueue(_) => {
+ try_or_throw!(self.machine_st, self.is_consistent_with_term_queue());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::ExecuteIsConsistentWithTermQueue(_) => {
+ try_or_throw!(self.machine_st, self.is_consistent_with_term_queue());
+ step_or_fail!(self, self.machine_st.p += 1);
+ }
+ &Instruction::CallFlushTermQueue(_) => {
+ try_or_throw!(self.machine_st, self.flush_term_queue());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteFlushTermQueue(_) => {
+ try_or_throw!(self.machine_st, self.flush_term_queue());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallRemoveModuleExports(_) => {
+ try_or_throw!(self.machine_st, self.remove_module_exports());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteRemoveModuleExports(_) => {
+ try_or_throw!(self.machine_st, self.remove_module_exports());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ &Instruction::CallAddNonCountedBacktracking(_) => {
+ try_or_throw!(self.machine_st, self.add_non_counted_backtracking());
+ self.machine_st.p += 1;
+ }
+ &Instruction::ExecuteAddNonCountedBacktracking(_) => {
+ try_or_throw!(self.machine_st, self.add_non_counted_backtracking());
+ self.machine_st.p = self.machine_st.cp;
+ }
+ }
+ }
+
+ let interrupted = INTERRUPT.load(std::sync::atomic::Ordering::Relaxed);
+
+ match INTERRUPT.compare_exchange(
+ interrupted,
+ false,
+ std::sync::atomic::Ordering::Relaxed,
+ std::sync::atomic::Ordering::Relaxed,
+ ) {
+ Ok(interruption) => {
+ if interruption {
+ self.machine_st.throw_interrupt_exception();
+ self.machine_st.backtrack();
+ }
+ }
+ Err(_) => unreachable!(),
+ }
}
}
}
use core::marker::PhantomData;
-// TODO: rename to 'unmark_if_iter', 'mark_if_gc'
pub(crate) trait UnmarkPolicy {
fn unmark(heap: &mut [HeapCellValue], current: usize) -> bool;
fn mark(heap: &mut [HeapCellValue], current: usize);
use crate::arena::*;
use crate::atom_table::*;
use crate::forms::*;
-use crate::machine::machine_indices::*;
use crate::machine::partial_string::*;
use crate::parser::ast::*;
use crate::types::*;
filtered_iter_to_heap_list(heap, values, |_, _| true)
}
-pub(crate) fn to_local_code_ptr(heap: &Heap, addr: HeapCellValue) -> Option<LocalCodePtr> {
+pub(crate) fn to_local_code_ptr(heap: &Heap, addr: HeapCellValue) -> Option<usize> {
let extract_integer = |s: usize| -> Option<usize> {
match Number::try_from(heap[s]) {
Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
let (name, arity) = cell_as_atom_cell!(heap[s]).get_name_and_arity();
if name == atom!("dir_entry") && arity == 1 {
- extract_integer(s+1).map(LocalCodePtr::DirEntry)
+ extract_integer(s+1)
} else {
panic!(
"to_local_code_ptr crashed with p.i. {}/{}",
}
)
}
-
-/*
-impl<T: RawBlockTraits> HeapTemplate<T> {
- #[inline]
- pub(crate) fn new() -> Self {
- HeapTemplate {
- buf: RawBlock::new(),
- _marker: PhantomData,
- }
- }
-
- /*
- // TODO: move this to the WAM, then remove the temporary (and by
- // then, unnecessary and impossible) "arena" argument. OR, remove
- // this thing totally! if we can. by that I mean, just convert a
- // little to a HeapCellValue. don't bother writing to the
- // heap at all. Each of these data is either already inlinable in a
- // HeapCellValue or a pointer to an GC'ed location in memory.
- #[inline]
- pub(crate) fn put_literal(&mut self, literal: Literal) -> HeapCellValue {
- match literal {
- Literal::Atom(name) => atom_as_cell!(name),
- Literal::Char(c) => char_as_cell!(c),
- Literal::EmptyList => empty_list_as_cell!(),
- Literal::Fixnum(n) => fixnum_as_cell!(n),
- Literal::Integer(bigint_ptr) => {
- let h = self.push(typed_arena_ptr_as_cell!(bigint_ptr));
- self[h]
- }
- Literal::Rational(bigint_ptr) => {
- let h = self.push(typed_arena_ptr_as_cell!(bigint_ptr));
- self[h]
- }
- Literal::Float(f) => typed_arena_ptr_as_cell!(f),
- Literal::String(s) => {
- if s.as_str().is_empty() {
- empty_list_as_cell!()
- } else {
- // TODO: how do we know where the tail is located?? well, there is no tail. separate tag?
- untyped_arena_ptr_as_cell!(s) // self.put_complete_string(arena, &s)
- }
- } // Literal::Usize(n) => Addr::Usize(n),
- }
- }
- */
-
- #[inline]
- pub(crate) fn is_empty(&self) -> bool {
- self.h() == 0
- }
-
- #[inline]
- pub(crate) fn pop(&mut self) {
- let h = self.h();
-
- if h > 0 {
- self.truncate(h - 1);
- }
- }
-
- #[inline]
- pub(crate) fn push(&mut self, val: HeapCellValue) -> usize {
- let h = self.h();
-
- unsafe {
- let new_ptr = self.buf.alloc(mem::size_of::<HeapCellValue>());
- ptr::write(new_ptr as *mut _, val);
- }
-
- h
- }
-
- /*
- #[inline]
- pub(crate) fn atom_at(&self, h: usize) -> bool {
- if let HeapCellValue::Atom(..) = &self[h] {
- true
- } else {
- false
- }
- }
-
- #[inline]
- pub(crate) fn to_unifiable(&mut self, non_heap_value: HeapCellValue) -> Addr {
- match non_heap_value {
- HeapCellValue::Addr(addr) => addr,
- val @ HeapCellValue::Atom(..)
- | val @ HeapCellValue::Integer(_)
- | val @ HeapCellValue::DBRef(_)
- | val @ HeapCellValue::Rational(_) => Addr::Con(self.push(val)),
- val @ HeapCellValue::LoadStatePayload(_) => Addr::LoadStatePayload(self.push(val)),
- val @ HeapCellValue::NamedStr(..) => Addr::Str(self.push(val)),
- HeapCellValue::PartialString(pstr, has_tail) => {
- let h = self.push(HeapCellValue::PartialString(pstr, has_tail));
-
- if has_tail {
- self.push(HeapCellValue::Addr(Addr::EmptyList));
- }
-
- Addr::Con(h)
- }
- val @ HeapCellValue::Stream(..) => Addr::Stream(self.push(val)),
- val @ HeapCellValue::TcpListener(..) => Addr::TcpListener(self.push(val)),
- }
- }
- */
-
- #[inline]
- pub(crate) fn truncate(&mut self, h: usize) {
- let new_ptr = self.buf.top as usize - h * mem::size_of::<HeapCellValue>();
- self.buf.ptr = new_ptr as *mut _;
- }
-
- #[inline]
- pub(crate) fn h(&self) -> usize {
- (self.buf.top as usize - self.buf.ptr as usize) / mem::size_of::<HeapCellValue>()
- }
-
- pub(crate) fn append(&mut self, vals: Vec<HeapCellValue>) {
- for val in vals {
- self.push(val);
- }
- }
-
- pub(crate) fn clear(&mut self) {
- if !self.buf.base.is_null() {
- self.truncate(0);
- self.buf.top = self.buf.base;
- }
- }
-
- /* TODO: get rid of this!!
- #[inline]
- pub(crate) fn index_addr<'a>(&'a self, addr: &Addr) -> RefOrOwned<'a, HeapCellValue> {
- match addr {
- &Addr::Con(h) | &Addr::Str(h) | &Addr::Stream(h) | &Addr::TcpListener(h) => {
- RefOrOwned::Borrowed(&self[h])
- }
- addr => RefOrOwned::Owned(HeapCellValue::Addr(*addr)),
- }
- }
- */
-}
-
-impl<T: RawBlockTraits> Index<u64> for HeapTemplate<T> {
- type Output = HeapCellValue;
-
- #[inline]
- fn index(&self, index: u64) -> &Self::Output {
- unsafe {
- let ptr =
- self.buf.top as usize - (index as usize + 1) * mem::size_of::<HeapCellValue>();
- &*(ptr as *const HeapCellValue)
- }
- }
-}
-
-impl<T: RawBlockTraits> Index<usize> for HeapTemplate<T> {
- type Output = HeapCellValue;
-
- #[inline]
- fn index(&self, index: usize) -> &Self::Output {
- unsafe {
- let ptr = self.buf.top as usize - (index + 1) * mem::size_of::<HeapCellValue>();
- &*(ptr as *const HeapCellValue)
- }
- }
-}
-
-impl<T: RawBlockTraits> IndexMut<usize> for HeapTemplate<T> {
- #[inline]
- fn index_mut(&mut self, index: usize) -> &mut Self::Output {
- unsafe {
- let ptr = self.buf.top as usize - (index + 1) * mem::size_of::<HeapCellValue>();
- &mut *(ptr as *mut HeapCellValue)
- }
- }
-}
-*/
-use crate::clause_types::*;
use crate::forms::*;
use crate::machine::loader::*;
use crate::machine::machine_errors::*;
use crate::machine::*;
use crate::parser::ast::*;
+use fxhash::FxBuildHasher;
use indexmap::IndexSet;
use ref_thread_local::RefThreadLocal;
use slice_deque::{sdeq, SliceDeque};
pub(super) fn get_clause_type(&mut self, name: Atom, arity: usize) -> ClauseType {
match ClauseType::from(name, arity) {
- ClauseType::Named(name, arity, _) => {
+ ClauseType::Named(arity, name, _) => {
let payload_compilation_target = self.payload.compilation_target;
let idx = self.get_or_insert_code_index(
payload_compilation_target,
);
- ClauseType::Named(name, arity, idx)
+ ClauseType::Named(arity, name, idx)
}
ct => ct,
}
arity: usize,
) -> ClauseType {
match ClauseType::from(name, arity) {
- ClauseType::Named(name, arity, _) => {
+ ClauseType::Named(arity, name, _) => {
let key = (name, arity);
let idx = self.get_or_insert_qualified_code_index(module_name, key);
- ClauseType::Named(name, arity, idx)
+ ClauseType::Named(arity, name, idx)
}
ct => ct,
}
let local_extensible_predicates = mem::replace(
&mut module.local_extensible_predicates,
- LocalExtensiblePredicates::new(),
+ LocalExtensiblePredicates::with_hasher(FxBuildHasher::default()),
);
for ((compilation_target, key), skeleton) in local_extensible_predicates.iter() {
let subloader: Loader<'_, BootstrappingLoadState> = Loader {
payload: BootstrappingLoadState(
- LoadStatePayload::new(self.wam_prelude.code_repo.code.len(), term_stream)
+ LoadStatePayload::new(self.wam_prelude.code.len(), term_stream)
),
wam_prelude: MachinePreludeView {
indices: self.wam_prelude.indices,
- code_repo: self.wam_prelude.code_repo,
+ code: self.wam_prelude.code,
load_contexts: self.wam_prelude.load_contexts,
}
};
let subloader: Loader<'_, BootstrappingLoadState> = Loader {
payload: BootstrappingLoadState(
- LoadStatePayload::new(self.wam_prelude.code_repo.code.len(), term_stream),
+ LoadStatePayload::new(self.wam_prelude.code.len(), term_stream),
),
wam_prelude: MachinePreludeView {
indices: self.wam_prelude.indices,
- code_repo: self.wam_prelude.code_repo,
+ code: self.wam_prelude.code,
load_contexts: self.wam_prelude.load_contexts,
}
};
use crate::arena::*;
use crate::atom_table::*;
-use crate::clause_types::*;
use crate::forms::*;
use crate::heap_iter::*;
use crate::indexing::*;
loader.compile_and_submit()?;
}
- let repo_len = loader.wam_prelude.code_repo.code.len();
+ let repo_len = loader.wam_prelude.code.len();
loader
.payload
impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
#[inline]
pub(super) fn new(wam: &'a mut Machine, term_stream: <LS as LoadState<'a>>::TS) -> Self {
- let payload = LoadStatePayload::new(wam.code_repo.code.len(), term_stream);
+ let payload = LoadStatePayload::new(wam.code.len(), term_stream);
let (wam_prelude, machine_st) = wam.prelude_view_and_machine_st();
Self {
RetractionRecord::AddedIndex(index_key, clause_loc) => {
// WAS: inner_index_locs) => {
if let Some(index_loc) = index_key.switch_on_term_loc() {
- let indexing_code = match &mut self.wam_prelude.code_repo.code[index_loc] {
- Line::IndexingCode(indexing_code) => indexing_code,
+ let indexing_code = match &mut self.wam_prelude.code[index_loc] {
+ Instruction::IndexingCode(indexing_code) => indexing_code,
_ => {
unreachable!()
}
// write the retraction logic of this arm.
}
RetractionRecord::ReplacedChoiceOffset(instr_loc, offset) => {
- match self.wam_prelude.code_repo.code[instr_loc] {
- Line::Choice(ChoiceInstruction::TryMeElse(ref mut o))
- | Line::Choice(ChoiceInstruction::RetryMeElse(ref mut o))
- | Line::Choice(ChoiceInstruction::DefaultRetryMeElse(ref mut o)) => {
+ match self.wam_prelude.code[instr_loc] {
+ Instruction::TryMeElse(ref mut o) |
+ Instruction::RetryMeElse(ref mut o) |
+ Instruction::DefaultRetryMeElse(ref mut o) => {
*o = offset;
}
_ => {
}
}
RetractionRecord::AppendedTrustMe(instr_loc, offset, is_default) => {
- match self.wam_prelude.code_repo.code[instr_loc] {
- Line::Choice(ref mut choice_instr) => {
- *choice_instr = if is_default {
- ChoiceInstruction::DefaultTrustMe(offset)
- } else {
- ChoiceInstruction::TrustMe(offset)
- };
- }
- _ => {
- unreachable!();
- }
- }
+ self.wam_prelude.code[instr_loc] = if is_default {
+ Instruction::DefaultTrustMe(offset)
+ } else {
+ Instruction::TrustMe(offset)
+ };
}
RetractionRecord::ReplacedSwitchOnTermVarIndex(index_loc, old_v) => {
- match self.wam_prelude.code_repo.code[index_loc] {
- Line::IndexingCode(ref mut indexing_code) => match &mut indexing_code[0] {
+ match self.wam_prelude.code[index_loc] {
+ Instruction::IndexingCode(ref mut indexing_code) => match &mut indexing_code[0] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(
_,
ref mut v,
}
}
RetractionRecord::ModifiedTryMeElse(instr_loc, o) => {
- self.wam_prelude.code_repo.code[instr_loc] =
- Line::Choice(ChoiceInstruction::TryMeElse(o));
+ self.wam_prelude.code[instr_loc] = Instruction::TryMeElse(o);
}
RetractionRecord::ModifiedRetryMeElse(instr_loc, o) => {
- self.wam_prelude.code_repo.code[instr_loc] =
- Line::Choice(ChoiceInstruction::RetryMeElse(o));
+ self.wam_prelude.code[instr_loc] = Instruction::RetryMeElse(o);
}
RetractionRecord::ModifiedRevJmpBy(instr_loc, o) => {
- self.wam_prelude.code_repo.code[instr_loc] =
- Line::Control(ControlInstruction::RevJmpBy(o));
+ self.wam_prelude.code[instr_loc] = Instruction::RevJmpBy(o);
}
RetractionRecord::SkeletonClausePopBack(compilation_target, key) => {
match self
}
}
RetractionRecord::ReplacedIndexingLine(index_loc, indexing_code) => {
- self.wam_prelude.code_repo.code[index_loc] = Line::IndexingCode(indexing_code);
+ self.wam_prelude.code[index_loc] = Instruction::IndexingCode(indexing_code);
}
RetractionRecord::RemovedLocalSkeletonClauseLocations(
compilation_target,
}
}
RetractionRecord::ReplacedDynamicElseOffset(instr_loc, next) => {
- match self.wam_prelude.code_repo.code[instr_loc] {
- Line::Choice(ChoiceInstruction::DynamicElse(
+ match self.wam_prelude.code[instr_loc] {
+ Instruction::DynamicElse(
_,
_,
NextOrFail::Next(ref mut o),
- ))
- | Line::Choice(ChoiceInstruction::DynamicInternalElse(
+ )
+ | Instruction::DynamicInternalElse(
_,
_,
NextOrFail::Next(ref mut o),
- )) => {
+ ) => {
*o = next;
}
_ => {}
}
}
RetractionRecord::AppendedNextOrFail(instr_loc, fail) => {
- match self.wam_prelude.code_repo.code[instr_loc] {
- Line::Choice(ChoiceInstruction::DynamicElse(
+ match self.wam_prelude.code[instr_loc] {
+ Instruction::DynamicElse(
_,
_,
ref mut next_or_fail,
- ))
- | Line::Choice(ChoiceInstruction::DynamicInternalElse(
+ )
+ | Instruction::DynamicInternalElse(
_,
_,
ref mut next_or_fail,
- )) => {
+ ) => {
*next_or_fail = fail;
}
_ => {}
}
impl Machine {
- pub(crate) fn use_module(&mut self) {
+ pub(crate) fn use_module(&mut self) -> CallResult {
let subevacuable_addr = self
.machine_st
.store(self.machine_st.deref(self.machine_st.registers[2]));
match payload.compilation_target {
CompilationTarget::Module(module_name) => module_name,
CompilationTarget::User => {
- return;
+ return Ok(());
}
}
});
};
let result = use_module();
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
}
- pub(crate) fn load_compiled_library(&mut self) {
+ pub(crate) fn load_compiled_library(&mut self) -> CallResult {
let library = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
if let Some(module) = self.indices.modules.get(&library) {
if let ListingSource::DynamicallyGenerated = module.listing_src {
self.machine_st.fail = true;
- return;
+ return Ok(());
}
let mut loader = self.loader_from_heap_evacuable(temp_v!(3));
};
let result = import_module();
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
} else {
self.machine_st.fail = true;
+ Ok(())
}
}
- pub(crate) fn declare_module(&mut self) {
+ pub(crate) fn declare_module(&mut self) -> CallResult {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
};
let result = declare_module();
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
}
#[inline]
- pub(crate) fn add_discontiguous_predicate(&mut self) {
+ pub(crate) fn add_discontiguous_predicate(&mut self) -> CallResult {
self.add_extensible_predicate_declaration(
|loader, compilation_target, clause_name, arity| {
loader.add_discontiguous_predicate(compilation_target, clause_name, arity)
},
- );
+ )
}
#[inline]
- pub(crate) fn add_dynamic_predicate(&mut self) {
+ pub(crate) fn add_dynamic_predicate(&mut self) -> CallResult {
self.add_extensible_predicate_declaration(
|loader, compilation_target, clause_name, arity| {
loader.add_dynamic_predicate(compilation_target, clause_name, arity)
},
- );
+ )
}
#[inline]
- pub(crate) fn add_multifile_predicate(&mut self) {
+ pub(crate) fn add_multifile_predicate(&mut self) -> CallResult {
self.add_extensible_predicate_declaration(
|loader, compilation_target, clause_name, arity| {
loader.add_multifile_predicate(compilation_target, clause_name, arity)
},
- );
+ )
}
fn add_extensible_predicate_declaration(
Atom,
usize,
) -> Result<(), SessionError>,
- ) {
+ ) -> CallResult {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
};
let result = add_predicate_decl();
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
}
- pub(crate) fn add_term_expansion_clause(&mut self) {
+ pub(crate) fn add_term_expansion_clause(&mut self) -> CallResult {
let mut loader = self.loader_from_heap_evacuable(temp_v!(2));
let add_clause = || {
};
let result = add_clause();
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
}
- pub(crate) fn add_goal_expansion_clause(&mut self) {
+ pub(crate) fn add_goal_expansion_clause(&mut self) -> CallResult {
let target_module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
};
let result = add_clause();
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
}
- pub(crate) fn add_in_situ_filename_module(&mut self) {
+ pub(crate) fn add_in_situ_filename_module(&mut self) -> CallResult {
let mut loader = self.loader_from_heap_evacuable(temp_v!(1));
let add_in_situ_filename_module = || {
};
let result = add_in_situ_filename_module();
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
}
pub(crate) fn loader_from_heap_evacuable<'a>(
pub(crate) fn push_load_state_payload(&mut self) {
let payload = arena_alloc!(
LoadStatePayload::new(
- self.code_repo.code.len(),
+ self.code.len(),
LiveTermStream::new(ListingSource::User),
),
&mut self.machine_st.arena
);
- let var = self.machine_st.deref(
- self.machine_st.registers[1]
- );
+ let var = self.machine_st.deref(self.machine_st.registers[1]);
self.machine_st.bind(
var.as_var().unwrap(),
self.load_contexts.pop();
}
- pub(crate) fn push_load_context(&mut self) {
- let stream = try_or_fail!(
- self.machine_st,
- self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("$push_load_context"),
- 2,
- )
- );
+ pub(crate) fn push_load_context(&mut self) -> CallResult {
+ let stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("$push_load_context"),
+ 2,
+ )?;
let path = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]))
);
self.load_contexts.push(LoadContext::new(path.as_str(), stream));
+ Ok(())
}
pub(crate) fn restore_load_state_payload(
&mut self,
result: Result<TypedArenaPtr<LiveLoadState>, SessionError>,
- ) {
+ ) -> CallResult {
match result {
Ok(_payload) => {
+ Ok(())
}
Err(e) => {
- self.throw_session_error(e, (atom!("load"), 1));
+ let err = self.machine_st.session_error(e);
+ let stub = functor_stub(atom!("load"), 1);
+
+ Err(self.machine_st.error_form(err, stub))
}
}
}
- pub(crate) fn scoped_clause_to_evacuable(&mut self) {
+ 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 result = loader.read_and_enqueue_term(temp_v!(2), compilation_target);
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
}
- pub(crate) fn clause_to_evacuable(&mut self) {
+ pub(crate) fn clause_to_evacuable(&mut self) -> CallResult {
let loader = self.loader_from_heap_evacuable(temp_v!(2));
let compilation_target = loader.payload.compilation_target;
let result = loader.read_and_enqueue_term(temp_v!(1), compilation_target);
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
}
- pub(crate) fn conclude_load(&mut self) {
+ pub(crate) fn conclude_load(&mut self) -> CallResult {
let mut loader = self.loader_from_heap_evacuable(temp_v!(1));
let compile_final_terms = || {
};
let result = compile_final_terms();
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
}
pub(crate) fn load_context_source(&mut self) {
}
}
- pub(crate) fn compile_assert<'a>(&'a mut self, append_or_prepend: AppendOrPrepend) {
+ pub(crate) fn compile_assert<'a>(&'a mut self, append_or_prepend: AppendOrPrepend) -> CallResult {
let key = self
.machine_st
.read_predicate_key(self.machine_st[temp_v!(3)], self.machine_st[temp_v!(4)]);
};
match compile_assert() {
- Ok(_) => {}
+ Ok(_) => Ok(()),
Err(e) => {
- let error_pi = match append_or_prepend {
- AppendOrPrepend::Append => (atom!("assertz"), 1),
- AppendOrPrepend::Prepend => (atom!("asserta"), 1),
+ let stub = match append_or_prepend {
+ AppendOrPrepend::Append => functor_stub(atom!("assertz"), 1),
+ AppendOrPrepend::Prepend => functor_stub(atom!("asserta"), 1),
};
+ let err = self.machine_st.session_error(e);
- self.throw_session_error(e, error_pi);
+ Err(self.machine_st.error_form(err, stub))
}
}
}
- pub(crate) fn abolish_clause(&mut self) {
+ pub(crate) fn abolish_clause(&mut self) -> CallResult {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
let key = self
.machine_st
- .read_predicate_key(self.machine_st[temp_v!(2)], self.machine_st[temp_v!(3)]);
+ .read_predicate_key(self.machine_st.registers[2], self.machine_st.registers[3]);
let compilation_target = match module_name {
atom!("user") => CompilationTarget::User,
};
match abolish_clause() {
- Ok(_) => {}
+ Ok(_) => Ok(()),
Err(e) => {
- self.throw_session_error(e, (atom!("abolish"), 1));
+ let stub = functor_stub(atom!("abolish"), 1);
+ let err = self.machine_st.session_error(e);
+ Err(self.machine_st.error_form(err, stub))
}
}
}
- pub(crate) fn retract_clause(&mut self) {
+ pub(crate) fn retract_clause(&mut self) -> CallResult {
let key = self
.machine_st
.read_predicate_key(self.machine_st[temp_v!(1)], self.machine_st[temp_v!(2)]);
};
match retract_clause() {
- Ok(_) => {}
+ Ok(_) => Ok(()),
Err(e) => {
- self.throw_session_error(e, (atom!("retract"), 1));
+ let stub = functor_stub(atom!("retract"), 1);
+ let err = self.machine_st.session_error(e);
+
+ Err(self.machine_st.error_form(err, stub))
}
}
}
- pub(crate) fn is_consistent_with_term_queue(&mut self) {
+ pub(crate) fn is_consistent_with_term_queue(&mut self) -> CallResult {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
|| !key.is_consistent(&loader.payload.predicates);
let result = LiveLoadAndMachineState::evacuate(loader);
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
}
- pub(crate) fn flush_term_queue(&mut self) {
+ pub(crate) fn flush_term_queue(&mut self) -> CallResult {
let mut loader = self.loader_from_heap_evacuable(temp_v!(1));
let flush_term_queue = || {
};
let result = flush_term_queue();
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
}
- pub(crate) fn remove_module_exports(&mut self) {
+ pub(crate) fn remove_module_exports(&mut self) -> CallResult {
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
};
let result = remove_module_exports();
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
}
- pub(crate) fn add_non_counted_backtracking(&mut self) {
+ pub(crate) fn add_non_counted_backtracking(&mut self) -> CallResult {
let key = self
.machine_st
.read_predicate_key(self.machine_st[temp_v!(1)], self.machine_st[temp_v!(2)]);
loader.payload.non_counted_bt_preds.insert(key);
let result = LiveLoadAndMachineState::evacuate(loader);
- self.restore_load_state_payload(result);
+ self.restore_load_state_payload(result)
}
pub(crate) fn meta_predicate_property(&mut self) {
.read_predicate_key(self.machine_st.registers[1], self.machine_st.registers[2]);
match ClauseType::from(key.0, key.1) {
- ClauseType::BuiltIn(_) | ClauseType::Inlined(..) | ClauseType::CallN => {
+ ClauseType::BuiltIn(_) | ClauseType::Inlined(..) | ClauseType::CallN(_) => {
return;
}
- ClauseType::Named(name, arity, _) => {
+ ClauseType::Named(arity, name, _) => {
if let Some(module) = self.indices.modules.get(&(atom!("builtins"))) {
self.machine_st.fail = !module.code_dir.contains_key(&(name, arity));
return;
pub(super) fn throw_exception(&mut self, err: MachineStub) {
let h = self.heap.len();
+ let err_len = err.len();
self.ball.boundary = 0;
self.ball.stub.truncate(0);
self.heap.extend(err.into_iter());
- self.registers[1] = str_loc_as_cell!(h);
+ self.registers[1] = if err_len == 1 {
+ heap_loc_as_cell!(h)
+ } else {
+ str_loc_as_cell!(h)
+ };
self.set_ball();
self.unwind_stack();
use crate::arena::*;
use crate::atom_table::*;
-use crate::clause_types::*;
use crate::fixtures::*;
use crate::forms::*;
use crate::instructions::*;
-use crate::machine::*;
-use crate::machine::heap::*;
use crate::machine::loader::*;
-use crate::machine::machine_errors::MachineStub;
use crate::machine::machine_state::*;
use crate::machine::streams::Stream;
+use fxhash::FxBuildHasher;
use indexmap::IndexMap;
use std::cell::Cell;
use std::cmp::Ordering;
use std::collections::BTreeSet;
-use std::ops::{Add, AddAssign, Deref, Sub, SubAssign};
+use std::ops::Deref;
use std::rc::Rc;
-// these statics store the locations of one-off control instructions
-// in the code vector.
-
-pub static HALT_CODE: usize = 0;
-
use crate::types::*;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) struct OrderedOpDirKey(pub(crate) Atom, pub(crate) Fixity);
}
}
+/*
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
pub enum REPLCodePtr {
AddDiscontiguousPredicate,
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum CodePtr {
- BuiltInClause(BuiltInClauseType, LocalCodePtr), // local is the successor call.
- CallN(usize, LocalCodePtr, bool), // arity, local, last call.
- Local(LocalCodePtr),
- REPL(REPLCodePtr, LocalCodePtr), // the REPL code, the return pointer.
+ BuiltInClause(BuiltInClauseType, usize), // local is the successor call.
+ CallN(usize, usize, bool), // arity, local, last call.
+ Local(usize),
+ REPL(REPLCodePtr, usize), // the REPL code, the return pointer.
VerifyAttrInterrupt(usize), // location of the verify attribute interrupt code in the CodeDir.
}
impl CodePtr {
- pub(crate) fn local(&self) -> LocalCodePtr {
+ pub(crate) fn local(&self) -> usize {
match self {
- &CodePtr::BuiltInClause(_, ref local)
- | &CodePtr::CallN(_, ref local, _)
- | &CodePtr::Local(ref local) => local.clone(),
- &CodePtr::VerifyAttrInterrupt(p) => LocalCodePtr::DirEntry(p),
- &CodePtr::REPL(_, p) => p, // | &CodePtr::DynamicTransaction(_, p) => p,
+ &CodePtr::BuiltInClause(_, ref local) |
+ &CodePtr::CallN(_, ref local, _) |
+ &CodePtr::Local(ref local) => *local,
+ &CodePtr::VerifyAttrInterrupt(p) => p,
+ &CodePtr::REPL(_, p) => p,
}
}
- #[inline]
- pub(crate) fn is_halt(&self) -> bool {
- if let CodePtr::Local(LocalCodePtr::Halt) = self {
- true
- } else {
- false
- }
- }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq)]
-pub enum LocalCodePtr {
- DirEntry(usize), // offset
- Halt,
- // IndexingBuf(usize, usize, usize), // DirEntry offset, first internal offset, second internal offset
- // TopLevel(usize, usize), // chunk_num, offset
-}
-
-impl Machine {
- pub(crate) fn is_reset_cont_marker(&self, p: LocalCodePtr) -> bool {
- match self.code_repo.lookup_instr(&self.machine_st, &CodePtr::Local(p)) {
- Some(line) => match line.as_ref(&self.code_repo.code) {
- Line::Control(ControlInstruction::CallClause(ref ct, ..)) => {
- if let ClauseType::System(SystemClauseType::ResetContinuationMarker) = *ct {
- return true;
- }
- }
- _ => {}
- },
- None => {}
- }
-
- false
- }
-}
-
-impl LocalCodePtr {
- pub fn assign_if_local(&mut self, cp: CodePtr) {
- match cp {
- CodePtr::Local(local) => *self = local,
- _ => {}
- }
- }
-
- #[inline]
- pub fn abs_loc(&self) -> usize {
- match self {
- LocalCodePtr::DirEntry(ref p) => *p,
- // LocalCodePtr::IndexingBuf(ref p, ..) => *p,
- LocalCodePtr::Halt => unreachable!(),
- }
- }
-
- pub(crate) fn as_functor(&self) -> MachineStub {
+ pub fn assign_if_local(&self, cp: &mut usize) {
match self {
- LocalCodePtr::DirEntry(p) => {
- functor!(atom!("dir_entry"), [fixnum(*p)])
- }
- LocalCodePtr::Halt => {
- functor!(atom!("halt"))
- }
- /*
- LocalCodePtr::IndexingBuf(p, o, i) => {
- functor!(
- atom!("indexed_buf"),
- [fixnum(*p), fixnum(*o), fixnum(*i)]
- )
- }
- */
- }
- }
-}
-
-impl Default for CodePtr {
- #[inline]
- fn default() -> Self {
- CodePtr::Local(LocalCodePtr::default())
- }
-}
-
-impl Default for LocalCodePtr {
- #[inline]
- fn default() -> Self {
- LocalCodePtr::DirEntry(0)
- }
-}
-
-impl Add<usize> for LocalCodePtr {
- type Output = LocalCodePtr;
-
- #[inline]
- fn add(self, rhs: usize) -> Self::Output {
- match self {
- LocalCodePtr::DirEntry(p) => LocalCodePtr::DirEntry(p + rhs),
- LocalCodePtr::Halt => unreachable!(),
- // LocalCodePtr::IndexingBuf(p, o, i) => LocalCodePtr::IndexingBuf(p, o, i + rhs),
- }
- }
-}
-
-impl Sub<usize> for LocalCodePtr {
- type Output = Option<LocalCodePtr>;
-
- #[inline]
- fn sub(self, rhs: usize) -> Self::Output {
- match self {
- LocalCodePtr::DirEntry(p) => p.checked_sub(rhs).map(LocalCodePtr::DirEntry),
- LocalCodePtr::Halt => unreachable!(),
- // LocalCodePtr::IndexingBuf(p, o, i) => i
- // .checked_sub(rhs)
- // .map(|r| LocalCodePtr::IndexingBuf(p, o, r)),
- }
- }
-}
-
-impl SubAssign<usize> for LocalCodePtr {
- #[inline]
- fn sub_assign(&mut self, rhs: usize) {
- match self {
- LocalCodePtr::DirEntry(ref mut p) => *p -= rhs,
- LocalCodePtr::Halt => unreachable!() // | LocalCodePtr::IndexingBuf(..) => unreachable!(),
- }
- }
-}
-
-impl AddAssign<usize> for LocalCodePtr {
- #[inline]
- fn add_assign(&mut self, rhs: usize) {
- match self {
- &mut LocalCodePtr::DirEntry(ref mut i) => *i += rhs,
- // | &mut LocalCodePtr::IndexingBuf(_, _, ref mut i) => *i += rhs,
- &mut LocalCodePtr::Halt => unreachable!(),
+ CodePtr::Local(local) => *cp = *local,
+ _ => {}
}
}
}
fn add(self, rhs: usize) -> Self::Output {
match self {
- p @ CodePtr::REPL(..) | p @ CodePtr::VerifyAttrInterrupt(_) => p,
+ p @ CodePtr::REPL(..) | p @ CodePtr::VerifyAttrInterrupt(_) => {
+ p
+ }
CodePtr::Local(local) => CodePtr::Local(local + rhs),
CodePtr::BuiltInClause(_, local) | CodePtr::CallN(_, local, _) => {
CodePtr::Local(local + rhs)
}
}
-pub(crate) type HeapVarDict = IndexMap<Rc<String>, HeapCellValue>;
-pub(crate) type AllocVarDict = IndexMap<Rc<String>, VarData>;
+impl Default for CodePtr {
+ #[inline]
+ fn default() -> Self {
+ CodePtr::Local(0)
+ }
+}
+*/
+
+pub(crate) type HeapVarDict = IndexMap<Rc<String>, HeapCellValue, FxBuildHasher>;
+pub(crate) type AllocVarDict = IndexMap<Rc<String>, VarData, FxBuildHasher>;
-pub(crate) type GlobalVarDir = IndexMap<Atom, (Ball, Option<HeapCellValue>)>;
+pub(crate) type GlobalVarDir = IndexMap<Atom, (Ball, Option<HeapCellValue>), FxBuildHasher>;
-pub(crate) type StreamAliasDir = IndexMap<Atom, Stream>;
+pub(crate) type StreamAliasDir = IndexMap<Atom, Stream, FxBuildHasher>;
pub(crate) type StreamDir = BTreeSet<Stream>;
-pub(crate) type MetaPredicateDir = IndexMap<PredicateKey, Vec<MetaSpec>>;
+pub(crate) type MetaPredicateDir = IndexMap<PredicateKey, Vec<MetaSpec>, FxBuildHasher>;
-pub(crate) type ExtensiblePredicates = IndexMap<PredicateKey, PredicateSkeleton>;
+pub(crate) type ExtensiblePredicates = IndexMap<PredicateKey, PredicateSkeleton, FxBuildHasher>;
pub(crate) type LocalExtensiblePredicates =
- IndexMap<(CompilationTarget, PredicateKey), LocalPredicateSkeleton>;
+ IndexMap<(CompilationTarget, PredicateKey), LocalPredicateSkeleton, FxBuildHasher>;
+
+pub(crate) type CodeDir = IndexMap<PredicateKey, CodeIndex, FxBuildHasher>;
#[derive(Debug)]
pub struct IndexStore {
) -> Option<CodeIndex> {
if module == atom!("user") {
match ClauseType::from(name, arity) {
- ClauseType::Named(name, arity, _) => self.code_dir.get(&(name, arity)).cloned(),
+ ClauseType::Named(arity, name, _) => self.code_dir.get(&(name, arity)).cloned(),
_ => None,
}
} else {
self.modules
.get(&module)
.and_then(|module| match ClauseType::from(name, arity) {
- ClauseType::Named(name, arity, _) => {
+ ClauseType::Named(arity, name, _) => {
module.code_dir.get(&(name, arity)).cloned()
}
_ => None,
#[inline]
pub(super) fn new() -> Self {
- index_store!(CodeDir::new(), default_op_dir(), ModuleDir::new())
+ index_store!(
+ CodeDir::with_hasher(FxBuildHasher::default()),
+ default_op_dir(),
+ ModuleDir::with_hasher(FxBuildHasher::default())
+ )
}
}
-
-pub(crate) type CodeDir = IndexMap<PredicateKey, CodeIndex>;
pub arena: Arena,
pub(super) pdl: Vec<HeapCellValue>,
pub(super) s: HeapPtr,
- pub(super) p: CodePtr,
+ pub(super) p: usize,
pub(super) oip: u32, // first internal code ptr
pub(super) iip : u32, // second internal code ptr
pub(super) b: usize,
pub(super) b0: usize,
pub(super) e: usize,
pub(super) num_of_args: usize,
- pub(super) cp: LocalCodePtr,
+ pub(super) cp: usize,
pub(super) attr_var_init: AttrVarInitializer,
pub(super) fail: bool,
pub heap: Heap,
// locations of cleaners, cut points, the previous block. for setup_call_cleanup.
pub(super) cont_pts: Vec<(HeapCellValue, usize, usize)>,
pub(super) cwil: CWIL,
- pub(super) last_call: bool, // TODO: REMOVE THIS.
pub(crate) flags: MachineFlags,
pub(crate) cc: usize,
pub(crate) global_clock: usize,
.field("ball", &self.ball)
.field("lifted_heap", &self.lifted_heap)
.field("interms", &self.interms)
- .field("last_call", &self.last_call)
.field("flags", &self.flags)
.field("cc", &self.cc)
.field("global_clock", &self.global_clock)
}
impl MachineState {
+ pub(crate) fn backtrack(&mut self) {
+ let b = self.b;
+ let or_frame = self.stack.index_or_frame(b);
+
+ self.b0 = or_frame.prelude.b0;
+ self.p = or_frame.prelude.bp;
+
+ self.oip = or_frame.prelude.boip;
+ self.iip = or_frame.prelude.biip;
+
+ self.pdl.clear();
+ self.fail = false;
+ }
+
pub(crate) fn increment_call_count(&mut self) -> CallResult {
if self.cwil.inference_limit_exceeded || self.ball.stub.len() > 0 {
return Ok(());
self.error_form(err, stub)
}
- pub(super) fn call_at_index(&mut self, arity: usize, p: LocalCodePtr) {
- self.cp.assign_if_local(self.p + 1);
+ #[inline(always)]
+ pub(super) fn call_at_index(&mut self, arity: usize, p: usize) {
+ self.cp = self.p + 1;
+ self.p = p;
self.num_of_args = arity;
self.b0 = self.b;
- self.p = CodePtr::Local(p);
}
- pub(super) fn execute_at_index(&mut self, arity: usize, p: LocalCodePtr) {
+ #[inline(always)]
+ pub(super) fn execute_at_index(&mut self, arity: usize, p: usize) {
self.num_of_args = arity;
self.b0 = self.b;
- self.p = CodePtr::Local(p);
+ self.p = p;
}
pub fn read_term(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult {
if stream.past_end_of_stream() {
if EOFAction::Reset != stream.options().eof_action() {
- return return_from_clause!(self.last_call, self);
+ return Ok(());
} else if self.fail {
return Ok(());
}
or_frame.prelude.e = self.e;
or_frame.prelude.cp = self.cp;
or_frame.prelude.b = self.b;
- or_frame.prelude.bp = self.p.local() + offset;
+ or_frame.prelude.bp = self.p + offset;
or_frame.prelude.boip = 0;
or_frame.prelude.biip = 0;
or_frame.prelude.tr = self.tr;
self.b = b;
for i in 0..n {
- self.stack[stack_loc!(OrFrame, b, i)] = self.registers[i+1];
+ or_frame[i] = self.registers[i+1];
}
self.hb = self.heap.len();
or_frame.prelude.e = self.e;
or_frame.prelude.cp = self.cp;
or_frame.prelude.b = self.b;
- or_frame.prelude.bp = self.p.local(); // + 1; in self.iip now!
+ or_frame.prelude.bp = self.p; // + 1; in self.iip now!
or_frame.prelude.boip = self.oip;
or_frame.prelude.biip = self.iip + 1;
or_frame.prelude.tr = self.tr;
}
self.hb = self.heap.len();
- self.p = CodePtr::Local(dir_entry!(self.p.local().abs_loc() + offset));
+ self.p = self.p + offset;
self.oip = 0;
self.iip = 0;
use crate::arena::*;
use crate::atom_table::*;
use crate::types::*;
-use crate::clause_types::*;
use crate::forms::*;
use crate::heap_iter::*;
use crate::machine::attributed_variables::*;
use crate::machine::copier::*;
use crate::machine::heap::*;
-use crate::machine::Machine;
use crate::machine::machine_errors::*;
use crate::machine::machine_indices::*;
use crate::machine::machine_state::*;
use std::cmp::Ordering;
use std::convert::TryFrom;
-// TODO: move this block to.. a place.
-impl Machine {
-
-}
-
impl MachineState {
pub(crate) fn new() -> Self {
MachineState {
atom_tbl: AtomTable::new(),
pdl: Vec::with_capacity(1024),
s: HeapPtr::default(),
- p: CodePtr::default(),
+ p: 0,
oip: 0,
iip: 0,
b: 0,
b0: 0,
e: 0,
num_of_args: 0,
- cp: LocalCodePtr::default(),
+ cp: 0,
attr_var_init: AttrVarInitializer::new(0),
fail: false,
heap: Heap::with_capacity(256 * 256),
interms: vec![Number::default();256],
cont_pts: Vec::with_capacity(256),
cwil: CWIL::new(),
- last_call: false,
flags: MachineFlags::default(),
cc: 0,
global_clock: 0,
match r1.get_tag() {
RefTag::StackCell => {
self.stack[r1.get_value() as usize] = t2;
+ self.trail(TrailRef::Ref(r1));
}
RefTag::HeapCell => {
self.heap[r1.get_value() as usize] = t2;
+ self.trail(TrailRef::Ref(r1));
}
RefTag::AttrVar => {
self.bind_attr_var(r1.get_value() as usize, t2);
}
};
-
- self.trail(TrailRef::Ref(r1));
} else {
read_heap_cell!(a2,
(HeapCellValueTag::StackVar, s) => {
);
}
- pub fn copy_term(&mut self, attr_var_policy: AttrVarPolicy) {
- let old_h = self.heap.len();
-
- let a1 = self.registers[1];
- let a2 = self.registers[2];
-
- copy_term(CopyTerm::new(self), a1, attr_var_policy);
-
- unify_fn!(*self, heap_loc_as_cell!(old_h), a2);
- }
-
pub(super) fn unwind_stack(&mut self) {
self.b = self.block;
self.fail = true;
);
}
Some(PStrPrefixCmpResult { prefix_len, .. }) => {
- // TODO: this is woefully insufficient! you need to
- // match the remaining portion of string if offset <
- // pstr.len().
let focus = heap_pstr_iter.focus();
let tail_addr = self.heap[focus];
)
}
- pub(super) fn handle_internal_call_n(&mut self, arity: usize) {
- let arity = arity + 1;
- let pred = self.registers[1];
-
- for i in 2..arity {
- self.registers[i - 1] = self.registers[i];
- }
-
- if arity > 1 {
- self.registers[arity - 1] = pred;
- return;
- }
-
- self.fail = true;
- }
-
- pub(super) fn setup_call_n(&mut self, arity: usize) -> Option<PredicateKey> {
+ pub(super) fn setup_call_n(&mut self, arity: usize) -> Result<PredicateKey, MachineStub> {
let addr = self.store(self.deref(self.registers[arity]));
let (name, narity) = read_heap_cell!(addr,
if narity + arity > MAX_ARITY {
let stub = functor_stub(atom!("call"), arity + 1);
let err = self.representation_error(RepFlag::MaxArity);
- let representation_error = self.error_form(err, stub);
-
- self.throw_exception(representation_error);
- return None;
+ return Err(self.error_form(err, stub));
}
for i in (1..arity).rev() {
(name, narity)
}
(HeapCellValueTag::Atom, (name, arity)) => {
- if arity == 0 {
- (name, 0)
- } else {
- self.fail = true;
- return None;
- }
+ debug_assert_eq!(arity, 0);
+ (name, 0)
}
(HeapCellValueTag::Char, c) => {
(self.atom_tbl.build_with(&c.to_string()), 0)
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar, _h) => {
let stub = functor_stub(atom!("call"), arity + 1);
let err = self.instantiation_error();
- let instantiation_error = self.error_form(err, stub);
-
- self.throw_exception(instantiation_error);
- return None;
+ return Err(self.error_form(err, stub));
}
_ => {
let stub = functor_stub(atom!("call"), arity + 1);
let err = self.type_error(ValidType::Callable, addr);
- let type_error = self.error_form(err, stub);
-
- self.throw_exception(type_error);
- return None;
+ return Err(self.error_form(err, stub));
}
);
- Some((name, arity + narity - 1))
+ Ok((name, arity + narity - 1))
}
#[inline]
Ok(())
}
- pub fn compare_numbers(&mut self, cmp: CompareNumberQT, n1: Number, n2: Number) {
- let ordering = n1.cmp(&n2);
-
- self.fail = match cmp {
- CompareNumberQT::GreaterThan if ordering == Ordering::Greater => false,
- CompareNumberQT::GreaterThanOrEqual if ordering != Ordering::Less => false,
- CompareNumberQT::LessThan if ordering == Ordering::Less => false,
- CompareNumberQT::LessThanOrEqual if ordering != Ordering::Greater => false,
- CompareNumberQT::NotEqual if ordering != Ordering::Equal => false,
- CompareNumberQT::Equal if ordering == Ordering::Equal => false,
- _ => true,
- };
-
- self.p += 1;
- }
-
- pub fn compare_term(&mut self, qt: CompareTermQT) {
- let a1 = self.registers[1];
- let a2 = self.registers[2];
-
- match compare_term_test!(self, a1, a2) {
- Some(Ordering::Greater) => match qt {
- CompareTermQT::GreaterThan | CompareTermQT::GreaterThanOrEqual => {}
- _ => self.fail = true,
- },
- Some(Ordering::Equal) => match qt {
- CompareTermQT::GreaterThanOrEqual | CompareTermQT::LessThanOrEqual => {}
- _ => self.fail = true,
- },
- Some(Ordering::Less) => match qt {
- CompareTermQT::LessThan | CompareTermQT::LessThanOrEqual => {}
- _ => self.fail = true,
- },
- None => {
- self.fail = true;
- }
- }
- }
-
// returns true on failure, false on success.
pub fn eq_test(&mut self, h1: HeapCellValue, h2: HeapCellValue) -> bool {
if h1 == h2 {
)
}
+ /*
pub fn setup_built_in_call(&mut self, ct: BuiltInClauseType) {
self.num_of_args = ct.arity();
self.b0 = self.b;
self.p = CodePtr::BuiltInClause(ct, self.p.local());
}
+ */
pub fn deallocate(&mut self) {
let e = self.e;
let mut wam = Machine {
machine_st,
indices: IndexStore::new(),
- code_repo: CodeRepo::new(),
+ code: Code::new(),
user_input,
user_output,
user_error,
lib_path.pop();
lib_path.push("lib");
+ wam.add_impls_to_indices();
+
bootstrapping_compile(
Stream::from_static_string(
LIBRARIES.borrow()["ops_and_meta_predicates"],
)
.unwrap();
- if let Some(builtins) = wam.indices.modules.get(&atom!("builtins")) {
+ if let Some(ref mut builtins) = wam.indices.modules.get_mut(&atom!("builtins")) {
load_module(
&mut wam.indices.code_dir,
&mut wam.indices.op_dir,
&CompilationTarget::User,
builtins,
);
+
+ import_builtin_impls(&wam.indices.code_dir, builtins);
} else {
unreachable!()
}
pub mod arithmetic_ops;
pub mod attributed_variables;
-pub mod code_repo;
pub mod code_walker;
#[macro_use]
pub mod loader;
pub mod system_calls;
pub mod term_stream;
-use crate::arena::*;
+use crate::arithmetic::*;
use crate::atom_table::*;
-use crate::clause_types::*;
use crate::forms::*;
-use crate::machine::code_repo::*;
+use crate::instructions::*;
use crate::machine::compile::*;
use crate::machine::copier::*;
use crate::machine::heap::*;
pub struct Machine {
pub(super) machine_st: MachineState,
pub(super) indices: IndexStore,
- pub(super) code_repo: CodeRepo,
+ pub(super) code: Code,
pub(super) user_input: Stream,
pub(super) user_output: Stream,
pub(super) user_error: Stream,
include!(concat!(env!("OUT_DIR"), "/libraries.rs"));
+pub static BREAK_FROM_DISPATCH_LOOP_LOC: usize = 0;
+pub static INSTALL_VERIFY_ATTR_INTERRUPT: usize = 1;
+pub static VERIFY_ATTR_INTERRUPT_LOC: usize = 2;
+
pub struct MachinePreludeView<'a> {
pub indices: &'a mut IndexStore,
- pub code_repo: &'a mut CodeRepo,
+ pub code: &'a mut Code,
pub load_contexts: &'a mut Vec<LoadContext>,
}
+pub(crate) fn import_builtin_impls(code_dir: &CodeDir, builtins: &mut Module) {
+ let keys = [
+ (atom!("@>"), 2),
+ (atom!("@<"), 2),
+ (atom!("@>="), 2),
+ (atom!("@=<"), 2),
+ (atom!("=="), 2),
+ (atom!("\\=="), 2),
+ (atom!(">"), 2),
+ (atom!("<"), 2),
+ (atom!(">="), 2),
+ (atom!("=<"), 2),
+ (atom!("=:="), 2),
+ (atom!("=\\="), 2),
+ (atom!("is"), 2),
+ (atom!("acyclic_term"), 1),
+ (atom!("arg"), 3),
+ (atom!("compare"), 3),
+ (atom!("copy_term"), 2),
+ (atom!("functor"), 3),
+ (atom!("ground"), 1),
+ (atom!("keysort"), 2),
+ (atom!("read"), 1),
+ (atom!("sort"), 2),
+ (atom!("$call"), 1),
+ (atom!("$call"), 2),
+ (atom!("$call"), 3),
+ (atom!("$call"), 4),
+ (atom!("$call"), 5),
+ (atom!("$call"), 6),
+ (atom!("$call"), 7),
+ (atom!("$call"), 8),
+ (atom!("$call"), 9),
+ (atom!("atom"), 1),
+ (atom!("atomic"), 1),
+ (atom!("compound"), 1),
+ (atom!("integer"), 1),
+ (atom!("number"), 1),
+ (atom!("rational"), 1),
+ (atom!("float"), 1),
+ (atom!("nonvar"), 1),
+ (atom!("var"), 1),
+ ];
+
+ for key in keys {
+ let idx = code_dir.get(&key).unwrap();
+ builtins.code_dir.insert(key, idx.clone());
+ builtins.module_decl.exports.push(ModuleExport::PredicateKey(key));
+ }
+}
+
impl Machine {
#[inline]
pub fn prelude_view_and_machine_st(&mut self) -> (MachinePreludeView, &mut MachineState) {
(
MachinePreludeView {
indices: &mut self.indices,
- code_repo: &mut self.code_repo,
+ code: &mut self.code,
load_contexts: &mut self.load_contexts,
},
&mut self.machine_st
let err = self.machine_st.error_form(err, stub);
self.machine_st.throw_exception(err);
- return;
}
fn run_module_predicate(&mut self, module_name: Atom, key: PredicateKey) {
if let Some(ref code_index) = module.code_dir.get(&key) {
let p = code_index.local().unwrap();
- self.machine_st.cp = LocalCodePtr::Halt;
- self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p));
+ self.machine_st.cp = BREAK_FROM_DISPATCH_LOOP_LOC;
+ self.machine_st.p = p;
- return self.run_query();
+ return self.dispatch_loop();
}
}
}
}
+ pub(crate) fn add_impls_to_indices(&mut self) {
+ let impls_offset = self.code.len() + 3;
+
+ self.code.extend(vec![
+ Instruction::BreakFromDispatchLoop,
+ Instruction::InstallVerifyAttr,
+ Instruction::VerifyAttrInterrupt,
+ Instruction::ExecuteTermGreaterThan(0),
+ Instruction::ExecuteTermLessThan(0),
+ Instruction::ExecuteTermGreaterThanOrEqual(0),
+ Instruction::ExecuteTermLessThanOrEqual(0),
+ Instruction::ExecuteTermEqual(0),
+ Instruction::ExecuteTermNotEqual(0),
+ Instruction::ExecuteNumberGreaterThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0),
+ Instruction::ExecuteNumberLessThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0),
+ Instruction::ExecuteNumberGreaterThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0),
+ Instruction::ExecuteNumberLessThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0),
+ Instruction::ExecuteNumberEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0),
+ Instruction::ExecuteNumberNotEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2)), 0),
+ Instruction::ExecuteIs(temp_v!(1), ar_reg!(temp_v!(2)), 0),
+ Instruction::ExecuteAcyclicTerm(0),
+ Instruction::ExecuteArg(0),
+ Instruction::ExecuteCompare(0),
+ Instruction::ExecuteCopyTerm(0),
+ Instruction::ExecuteFunctor(0),
+ Instruction::ExecuteGround(0),
+ Instruction::ExecuteKeySort(0),
+ Instruction::ExecuteRead(0),
+ Instruction::ExecuteSort(0),
+ Instruction::ExecuteN(1, 0),
+ Instruction::ExecuteN(2, 0),
+ Instruction::ExecuteN(3, 0),
+ Instruction::ExecuteN(4, 0),
+ Instruction::ExecuteN(5, 0),
+ Instruction::ExecuteN(6, 0),
+ Instruction::ExecuteN(7, 0),
+ Instruction::ExecuteN(8, 0),
+ Instruction::ExecuteN(9, 0),
+ Instruction::ExecuteIsAtom(temp_v!(1), 0),
+ Instruction::ExecuteIsAtomic(temp_v!(1), 0),
+ Instruction::ExecuteIsCompound(temp_v!(1), 0),
+ Instruction::ExecuteIsInteger(temp_v!(1), 0),
+ Instruction::ExecuteIsNumber(temp_v!(1), 0),
+ Instruction::ExecuteIsRational(temp_v!(1), 0),
+ Instruction::ExecuteIsFloat(temp_v!(1), 0),
+ Instruction::ExecuteIsNonVar(temp_v!(1), 0),
+ Instruction::ExecuteIsVar(temp_v!(1), 0)
+ ].into_iter());
+
+ for (p, instr) in self.code[impls_offset ..].iter().enumerate() {
+ let key = instr.to_name_and_arity();
+ self.indices.code_dir.insert(key, CodeIndex::new(IndexPtr::Index(p + impls_offset)));
+ }
+ }
+
pub fn new() -> Self {
use ref_thread_local::RefThreadLocal;
let mut wam = Machine {
machine_st,
indices: IndexStore::new(),
- code_repo: CodeRepo::new(),
+ code: vec![],
user_input,
user_output,
user_error,
lib_path.pop();
lib_path.push("lib");
+ wam.add_impls_to_indices();
+
bootstrapping_compile(
Stream::from_static_string(
LIBRARIES.borrow()["ops_and_meta_predicates"],
)
.unwrap();
- if let Some(builtins) = wam.indices.modules.get(&atom!("builtins")) {
+ if let Some(builtins) = wam.indices.modules.get_mut(&atom!("builtins")) {
load_module(
&mut wam.indices.code_dir,
&mut wam.indices.op_dir,
&CompilationTarget::User,
builtins,
);
+
+ import_builtin_impls(&wam.indices.code_dir, builtins);
} else {
unreachable!()
}
self.indices.streams.insert(self.user_error);
}
- fn handle_toplevel_command(&mut self, code_ptr: REPLCodePtr, p: LocalCodePtr) {
- match code_ptr {
- REPLCodePtr::AddDiscontiguousPredicate => {
- self.add_discontiguous_predicate();
- }
- REPLCodePtr::AddDynamicPredicate => {
- self.add_dynamic_predicate();
- }
- REPLCodePtr::AddMultifilePredicate => {
- self.add_multifile_predicate();
- }
- REPLCodePtr::AddGoalExpansionClause => {
- self.add_goal_expansion_clause();
- }
- REPLCodePtr::AddTermExpansionClause => {
- self.add_term_expansion_clause();
- }
- REPLCodePtr::AddInSituFilenameModule => {
- self.add_in_situ_filename_module();
- }
- REPLCodePtr::ClauseToEvacuable => {
- self.clause_to_evacuable();
- }
- REPLCodePtr::ScopedClauseToEvacuable => {
- self.scoped_clause_to_evacuable();
- }
- REPLCodePtr::ConcludeLoad => {
- self.conclude_load();
- }
- REPLCodePtr::PopLoadContext => {
- self.pop_load_context();
- }
- REPLCodePtr::PushLoadContext => {
- self.push_load_context();
- }
- REPLCodePtr::PopLoadStatePayload => {
- self.pop_load_state_payload();
- }
- REPLCodePtr::UseModule => {
- self.use_module();
- }
- REPLCodePtr::LoadCompiledLibrary => {
- self.load_compiled_library();
- }
- REPLCodePtr::DeclareModule => {
- self.declare_module();
- }
- REPLCodePtr::PushLoadStatePayload => {
- self.push_load_state_payload();
- }
- REPLCodePtr::LoadContextSource => {
- self.load_context_source();
- }
- REPLCodePtr::LoadContextFile => {
- self.load_context_file();
- }
- REPLCodePtr::LoadContextDirectory => {
- self.load_context_directory();
- }
- REPLCodePtr::LoadContextModule => {
- self.load_context_module();
- }
- REPLCodePtr::LoadContextStream => {
- self.load_context_stream();
- }
- REPLCodePtr::MetaPredicateProperty => {
- self.meta_predicate_property();
- }
- REPLCodePtr::BuiltInProperty => {
- self.builtin_property();
- }
- REPLCodePtr::MultifileProperty => {
- self.multifile_property();
- }
- REPLCodePtr::DiscontiguousProperty => {
- self.discontiguous_property();
- }
- REPLCodePtr::DynamicProperty => {
- self.dynamic_property();
- }
- REPLCodePtr::Assertz => {
- self.compile_assert(AppendOrPrepend::Append);
- }
- REPLCodePtr::Asserta => {
- self.compile_assert(AppendOrPrepend::Prepend);
- }
- REPLCodePtr::Retract => {
- self.retract_clause();
- }
- REPLCodePtr::AbolishClause => {
- self.abolish_clause();
- }
- REPLCodePtr::IsConsistentWithTermQueue => {
- self.is_consistent_with_term_queue();
- }
- REPLCodePtr::FlushTermQueue => {
- self.flush_term_queue();
- }
- REPLCodePtr::RemoveModuleExports => {
- self.remove_module_exports();
- }
- REPLCodePtr::AddNonCountedBacktracking => {
- self.add_non_counted_backtracking();
- }
- }
-
- self.machine_st.p = CodePtr::Local(p);
- }
-
- pub(crate) fn run_query(&mut self) {
- while !self.machine_st.p.is_halt() {
- self.query_stepper();
-
- match self.machine_st.p {
- CodePtr::REPL(code_ptr, p) => {
- self.handle_toplevel_command(code_ptr, p);
-
- if self.machine_st.fail {
- self.backtrack();
- }
- }
- _ => {
- break;
- }
- };
- }
- }
-
- fn execute_instr(&mut self) {
- let instr = match self.code_repo.lookup_instr(&self.machine_st, &self.machine_st.p) {
- Some(instr) => instr,
- None => return,
- };
-
- self.dispatch_instr(instr);
- }
-
- fn backtrack(&mut self) {
- let b = self.machine_st.b;
- let or_frame = self.machine_st.stack.index_or_frame(b);
-
- self.machine_st.b0 = or_frame.prelude.b0;
- self.machine_st.p = CodePtr::Local(or_frame.prelude.bp);
-
- self.machine_st.oip = or_frame.prelude.boip;
- self.machine_st.iip = or_frame.prelude.biip;
-
- self.machine_st.pdl.clear();
- self.machine_st.fail = false;
- }
-
- fn check_machine_index(&mut self) -> bool {
- match self.machine_st.p {
- CodePtr::Local(LocalCodePtr::DirEntry(p))
- if p < self.code_repo.code.len() => {}
- CodePtr::Local(LocalCodePtr::Halt) | CodePtr::REPL(..) => {
- return false;
- }
- _ => {}
- }
-
- true
- }
-
- // return true iff verify_attr_interrupt is called.
- fn verify_attr_stepper(&mut self) -> bool {
- loop {
- let instr = match self.code_repo.lookup_instr(&self.machine_st, &self.machine_st.p) {
- Some(instr) => {
- if instr.as_ref(&self.code_repo.code).is_head_instr() {
- instr
- } else {
- let cp = self.machine_st.p.local();
- self.run_verify_attr_interrupt(cp);
- return true;
- }
- }
- None => return false,
- };
-
- self.dispatch_instr(instr);
-
- if self.machine_st.fail {
- self.backtrack();
- }
-
- if !self.check_machine_index() {
- return false;
- }
- }
- }
-
- fn run_verify_attr_interrupt(&mut self, cp: LocalCodePtr) {
+ #[inline(always)]
+ pub(crate) fn run_verify_attr_interrupt(&mut self) { //, cp: usize) {
let p = self.machine_st.attr_var_init.verify_attrs_loc;
- self.machine_st.attr_var_init.cp = cp;
+ // self.machine_st.attr_var_init.cp = cp;
self.machine_st.verify_attr_interrupt(p);
}
- fn query_stepper(&mut self) {
- loop {
- self.execute_instr();
-
- if self.machine_st.fail {
- self.backtrack();
- }
-
- match self.machine_st.p {
- CodePtr::VerifyAttrInterrupt(_) => {
- self.machine_st.p = CodePtr::Local(self.machine_st.attr_var_init.cp);
-
- let instigating_p = CodePtr::Local(self.machine_st.attr_var_init.instigating_p);
- let instigating_instr = self.code_repo
- .lookup_instr(&self.machine_st, &instigating_p)
- .unwrap();
-
- if !instigating_instr.as_ref(&self.code_repo.code).is_head_instr() {
- let cp = self.machine_st.p.local();
- self.run_verify_attr_interrupt(cp);
- } else if !self.verify_attr_stepper() {
- if self.machine_st.fail {
- break;
- }
-
- let cp = self.machine_st.p.local();
- self.run_verify_attr_interrupt(cp);
- }
- }
- _ => {
- if !self.check_machine_index() {
- break;
- }
- }
- }
- }
- }
-
- pub fn execute_inlined(&mut self, inlined: &InlinedClauseType) {
- match inlined {
- &InlinedClauseType::CompareNumber(cmp, ref at_1, ref at_2) => {
- let n1 = try_or_fail!(self.machine_st, self.machine_st.get_number(at_1));
- let n2 = try_or_fail!(self.machine_st, self.machine_st.get_number(at_2));
-
- self.machine_st.compare_numbers(cmp, n1, n2);
- }
- &InlinedClauseType::IsAtom(r1) => {
- let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r1]));
-
- read_heap_cell!(d,
- (HeapCellValueTag::Atom, (_name, arity)) => {
- if arity == 0 {
- self.machine_st.p += 1;
- } else {
- self.machine_st.fail = true;
- }
- }
- (HeapCellValueTag::Char) => {
- self.machine_st.p += 1;
- }
- _ => {
- self.machine_st.fail = true;
- }
- );
- }
- &InlinedClauseType::IsAtomic(r1) => {
- let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r1]));
-
- read_heap_cell!(d,
- (HeapCellValueTag::Char | HeapCellValueTag::Fixnum | HeapCellValueTag::F64 |
- HeapCellValueTag::Cons) => {
- self.machine_st.p += 1;
- }
- (HeapCellValueTag::Atom, (_name, arity)) => {
- if arity == 0 {
- self.machine_st.p += 1;
- } else {
- self.machine_st.fail = true;
- }
- }
- _ => {
- self.machine_st.fail = true;
- }
- );
- }
- &InlinedClauseType::IsInteger(r1) => {
- let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r1]));
-
- match Number::try_from(d) {
- Ok(Number::Fixnum(_)) => {
- self.machine_st.p += 1;
- }
- Ok(Number::Integer(_)) => {
- self.machine_st.p += 1;
- }
- Ok(Number::Rational(n)) => {
- if n.denom() == &1 {
- self.machine_st.p += 1;
- } else {
- self.machine_st.fail = true;
- }
- }
- _ => {
- self.machine_st.fail = true;
- }
- }
- }
- &InlinedClauseType::IsCompound(r1) => {
- let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r1]));
-
- read_heap_cell!(d,
- (HeapCellValueTag::Str | HeapCellValueTag::Lis |
- HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => {
- self.machine_st.p += 1;
- }
- (HeapCellValueTag::Atom, (_name, arity)) => {
- if arity > 0 {
- self.machine_st.p += 1;
- } else {
- self.machine_st.fail = true;
- }
- }
- _ => {
- self.machine_st.fail = true;
- }
- );
- }
- &InlinedClauseType::IsFloat(r1) => {
- let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r1]));
-
- match Number::try_from(d) {
- Ok(Number::Float(_)) => {
- self.machine_st.p += 1;
- }
- _ => {
- self.machine_st.fail = true;
- }
- }
- }
- &InlinedClauseType::IsNumber(r1) => {
- let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r1]));
-
- match Number::try_from(d) {
- Ok(Number::Fixnum(_)) => {
- self.machine_st.p += 1;
- }
- Ok(Number::Integer(_)) => {
- self.machine_st.p += 1;
- }
- Ok(Number::Rational(n)) => {
- if n.denom() == &1 {
- self.machine_st.p += 1;
- } else {
- self.machine_st.fail = true;
- }
- }
- Ok(Number::Float(_)) => {
- self.machine_st.p += 1;
- }
- _ => {
- self.machine_st.fail = true;
- }
- }
- }
- &InlinedClauseType::IsRational(r1) => {
- let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r1]));
-
- read_heap_cell!(d,
- (HeapCellValueTag::Cons, ptr) => {
- match_untyped_arena_ptr!(ptr,
- (ArenaHeaderTag::Rational, _r) => {
- self.machine_st.p += 1;
- }
- _ => {
- self.machine_st.fail = true;
- }
- );
- }
- _ => {
- self.machine_st.fail = true;
- }
- );
- }
- &InlinedClauseType::IsNonVar(r1) => {
- let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r1]));
-
- match d.get_tag() {
- HeapCellValueTag::AttrVar
- | HeapCellValueTag::Var
- | HeapCellValueTag::StackVar => {
- self.machine_st.fail = true;
- }
- _ => {
- self.machine_st.p += 1;
- }
- }
- }
- &InlinedClauseType::IsVar(r1) => {
- let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r1]));
-
- match d.get_tag() {
- HeapCellValueTag::AttrVar |
- HeapCellValueTag::Var |
- HeapCellValueTag::StackVar => {
- self.machine_st.p += 1;
- }
- _ => {
- self.machine_st.fail = true;
- }
- }
- }
- }
- }
-
- #[inline(always)]
- pub(super) fn execute_dynamic_indexed_choice_instr(&mut self) {
- let p = self.machine_st.p.local();
-
- match self.find_living_dynamic(self.machine_st.oip, self.machine_st.iip) {
- Some((offset, oi, ii, is_next_clause)) => {
- self.machine_st.p = CodePtr::Local(LocalCodePtr::DirEntry(p.abs_loc()));
- self.machine_st.oip = oi;
- self.machine_st.iip = ii;
-
- match self.machine_st.dynamic_mode {
- FirstOrNext::First if !is_next_clause => {
- self.machine_st.p =
- CodePtr::Local(LocalCodePtr::DirEntry(p.abs_loc() + offset));
- }
- FirstOrNext::First => {
- // there's a leading DynamicElse that sets self.machine_st.cc.
- // self.machine_st.cc = self.machine_st.global_clock;
-
- // see that there is a following dynamic_else
- // clause so we avoid generating a choice
- // point in case there isn't.
- match self.find_living_dynamic(oi, ii + 1) {
- Some(_) => {
- self.machine_st.registers[self.machine_st.num_of_args + 1] =
- fixnum_as_cell!(Fixnum::build_with(self.machine_st.cc as i64));
-
- self.machine_st.num_of_args += 2;
- self.machine_st.indexed_try(offset);
- self.machine_st.num_of_args -= 2;
- }
- None => {
- self.machine_st.p =
- CodePtr::Local(LocalCodePtr::DirEntry(p.abs_loc() + offset));
- self.machine_st.oip = 0;
- self.machine_st.iip = 0;
- }
- }
- }
- FirstOrNext::Next => {
- let b = self.machine_st.b;
- let n = self.machine_st
- .stack
- .index_or_frame(b)
- .prelude
- .univ_prelude
- .num_cells;
-
- self.machine_st.cc = cell_as_fixnum!(
- self.machine_st.stack[stack_loc!(OrFrame, b, n-2)]
- ).get_num() as usize;
-
- if is_next_clause {
- match self.find_living_dynamic(self.machine_st.oip, self.machine_st.iip) {
- Some(_) => {
- self.retry(offset);
-
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- None => {
- self.trust(offset);
-
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- }
- } else {
- self.trust(offset);
-
- try_or_fail!(
- self.machine_st,
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
- );
- }
- }
- }
- }
- None => {
- self.machine_st.fail = true;
- }
- }
-
- self.machine_st.dynamic_mode = FirstOrNext::Next;
- }
-
#[inline(always)]
fn retry_me_else(&mut self, offset: usize) {
let b = self.machine_st.b;
self.machine_st.e = or_frame.prelude.e;
self.machine_st.cp = or_frame.prelude.cp;
- or_frame.prelude.bp = self.machine_st.p.local() + offset;
+ or_frame.prelude.bp = self.machine_st.p + offset;
let old_tr = or_frame.prelude.tr;
let curr_tr = self.machine_st.tr;
self.machine_st.tr = or_frame.prelude.tr;
- self.machine_st.attr_var_init.reset();
+ self.reset_attr_var_state();
self.machine_st.hb = self.machine_st.heap.len();
- self.machine_st.p += 1;
self.unwind_trail(old_tr, curr_tr);
self.machine_st.trail.truncate(self.machine_st.tr);
self.machine_st.heap.truncate(target_h);
+
+ self.machine_st.p += 1;
}
#[inline(always)]
self.machine_st.e = or_frame.prelude.e;
self.machine_st.cp = or_frame.prelude.cp;
- // WAS: or_frame.prelude.bp = self.machine_st.p.local() + 1;
+ // WAS: or_frame.prelude.bp = self.machine_st.p + 1;
or_frame.prelude.biip += 1;
let old_tr = or_frame.prelude.tr;
let target_h = or_frame.prelude.h;
self.machine_st.tr = or_frame.prelude.tr;
- self.machine_st.attr_var_init.reset();
+ self.reset_attr_var_state();
self.unwind_trail(old_tr, curr_tr);
self.machine_st.heap.truncate(target_h);
self.machine_st.hb = self.machine_st.heap.len();
- self.machine_st.p = CodePtr::Local(dir_entry!(self.machine_st.p.local().abs_loc() + offset));
+ self.machine_st.p = self.machine_st.p + offset;
self.machine_st.oip = 0;
self.machine_st.iip = 0;
let target_h = or_frame.prelude.h;
self.machine_st.tr = or_frame.prelude.tr;
-
- self.machine_st.attr_var_init.reset();
self.machine_st.b = or_frame.prelude.b;
+ self.reset_attr_var_state();
self.unwind_trail(old_tr, curr_tr);
self.machine_st.trail.truncate(self.machine_st.tr);
self.machine_st.heap.truncate(target_h);
self.machine_st.hb = self.machine_st.heap.len();
- self.machine_st.p = CodePtr::Local(dir_entry!(self.machine_st.p.local().abs_loc() + offset));
+ self.machine_st.p = self.machine_st.p + offset;
self.machine_st.oip = 0;
self.machine_st.iip = 0;
let target_h = or_frame.prelude.h;
self.machine_st.tr = or_frame.prelude.tr;
-
- self.machine_st.attr_var_init.reset();
self.machine_st.b = or_frame.prelude.b;
+ self.reset_attr_var_state();
self.unwind_trail(old_tr, curr_tr);
self.machine_st.trail.truncate(self.machine_st.tr);
}
#[inline(always)]
- fn context_call(&mut self, name: Atom, arity: usize, idx: CodeIndex) -> CallResult {
- if self.machine_st.last_call {
- self.try_execute(name, arity, idx)
- } else {
- self.try_call(name, arity, idx)
- }
- }
-
- #[inline(always)]
- fn try_call(&mut self, name: Atom, arity: usize, idx: CodeIndex) -> CallResult {
- match idx.get() {
+ fn try_call(&mut self, name: Atom, arity: usize, idx: IndexPtr) -> CallResult {
+ match idx {
IndexPtr::DynamicUndefined => {
self.machine_st.fail = true;
- return Ok(());
}
IndexPtr::Undefined => {
return Err(self.machine_st.throw_undefined_error(name, arity));
}
IndexPtr::DynamicIndex(compiled_tl_index) => {
self.machine_st.dynamic_mode = FirstOrNext::First;
- self.machine_st.call_at_index(arity, dir_entry!(compiled_tl_index));
+ self.machine_st.call_at_index(arity, compiled_tl_index);
}
IndexPtr::Index(compiled_tl_index) => {
- self.machine_st.call_at_index(arity, dir_entry!(compiled_tl_index));
+ self.machine_st.call_at_index(arity, compiled_tl_index);
}
}
}
#[inline(always)]
- fn try_execute(&mut self, name: Atom, arity: usize, idx: CodeIndex) -> CallResult {
- match idx.get() {
+ fn try_execute(&mut self, name: Atom, arity: usize, idx: IndexPtr) -> CallResult {
+ match idx {
IndexPtr::DynamicUndefined => {
self.machine_st.fail = true;
- return Ok(());
}
IndexPtr::Undefined => {
return Err(self.machine_st.throw_undefined_error(name, arity));
}
IndexPtr::DynamicIndex(compiled_tl_index) => {
self.machine_st.dynamic_mode = FirstOrNext::First;
- self.machine_st.execute_at_index(arity, dir_entry!(compiled_tl_index));
+ self.machine_st.execute_at_index(arity, compiled_tl_index);
}
IndexPtr::Index(compiled_tl_index) => {
- self.machine_st.execute_at_index(arity, dir_entry!(compiled_tl_index))
+ self.machine_st.execute_at_index(arity, compiled_tl_index)
}
}
}
#[inline(always)]
- fn call_builtin(&mut self, ct: &BuiltInClauseType) -> CallResult {
- match ct {
- &BuiltInClauseType::AcyclicTerm => {
- let addr = self.machine_st.registers[1];
- self.machine_st.fail = self.machine_st.is_cyclic_term(addr);
- return_from_clause!(self.machine_st.last_call, self.machine_st)
- }
- &BuiltInClauseType::Arg => {
- self.machine_st.try_arg()?;
- return_from_clause!(self.machine_st.last_call, self.machine_st)
- }
- &BuiltInClauseType::Compare => {
- let stub_gen = || functor_stub(atom!("compare"), 3);
-
- let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let a2 = self.machine_st.registers[2];
- let a3 = self.machine_st.registers[3];
-
- read_heap_cell!(a1,
- (HeapCellValueTag::Str, s) => {
- let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
- .get_name_and_arity();
-
- match name {
- atom!(">") | atom!("<") | atom!("=") if arity == 2 => {
- }
- _ => {
- let err = self.machine_st.domain_error(DomainErrorType::Order, a1);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
- }
- (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
- }
- _ => {
- let err = self.machine_st.type_error(ValidType::Atom, a1);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- );
-
- let atom = match compare_term_test!(self.machine_st, a2, a3) {
- Some(Ordering::Greater) => {
- atom!(">")
- }
- Some(Ordering::Equal) => {
- atom!("=")
- }
- None | Some(Ordering::Less) => {
- atom!("<")
- }
- };
-
- self.machine_st.unify_atom(atom, a1);
- return_from_clause!(self.machine_st.last_call, self.machine_st)
- }
- &BuiltInClauseType::CompareTerm(qt) => {
- self.machine_st.compare_term(qt);
- return_from_clause!(self.machine_st.last_call, self.machine_st)
- }
- &BuiltInClauseType::Read => {
- let stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("read"),
- 2,
- )?;
-
- match self.machine_st.read(stream, &self.indices.op_dir) {
- Ok(offset) => {
- let value = self.machine_st.registers[2];
- unify_fn!(&mut self.machine_st, value, heap_loc_as_cell!(offset.heap_loc));
- }
- Err(ParserError::UnexpectedEOF) => {
- let value = self.machine_st.registers[2];
- self.machine_st.unify_atom(atom!("end_of_file"), value);
- }
- Err(e) => {
- let stub = functor_stub(atom!("read"), 2);
- let err = self.machine_st.syntax_error(e);
-
- return Err(self.machine_st.error_form(err, stub));
- }
- };
-
- return_from_clause!(self.machine_st.last_call, self.machine_st)
- }
- &BuiltInClauseType::CopyTerm => {
- self.machine_st.copy_term(AttrVarPolicy::DeepCopy);
- return_from_clause!(self.machine_st.last_call, self.machine_st)
- }
- &BuiltInClauseType::Eq => {
- let a1 = self.machine_st.registers[1];
- let a2 = self.machine_st.registers[2];
-
- self.machine_st.fail = self.machine_st.eq_test(a1, a2);
- return_from_clause!(self.machine_st.last_call, self.machine_st)
- }
- &BuiltInClauseType::Ground => {
- self.machine_st.fail = self.machine_st.ground_test();
- return_from_clause!(self.machine_st.last_call, self.machine_st)
- }
- &BuiltInClauseType::Functor => {
- self.machine_st.try_functor()?;
- return_from_clause!(self.machine_st.last_call, self.machine_st)
- }
- &BuiltInClauseType::NotEq => {
- let a1 = self.machine_st.registers[1];
- let a2 = self.machine_st.registers[2];
-
- self.machine_st.fail =
- if let Some(Ordering::Equal) = compare_term_test!(self.machine_st, a1, a2) {
- true
- } else {
- false
- };
-
- return_from_clause!(self.machine_st.last_call, self.machine_st)
- }
- &BuiltInClauseType::Sort => {
- self.machine_st.check_sort_errors()?;
-
- let stub_gen = || functor_stub(atom!("sort"), 2);
- let mut list = self.machine_st.try_from_list(self.machine_st.registers[1], stub_gen)?;
-
- list.sort_unstable_by(|v1, v2| {
- compare_term_test!(self.machine_st, *v1, *v2).unwrap_or(Ordering::Less)
- });
-
- list.dedup_by(|v1, v2| {
- compare_term_test!(self.machine_st, *v1, *v2) == Some(Ordering::Equal)
- });
-
- let heap_addr = heap_loc_as_cell!(
- iter_to_heap_list(&mut self.machine_st.heap, list.into_iter())
- );
-
- let r2 = self.machine_st.registers[2];
- unify_fn!(&mut self.machine_st, r2, heap_addr);
-
- return_from_clause!(self.machine_st.last_call, self.machine_st)
- }
- &BuiltInClauseType::KeySort => {
- self.machine_st.check_keysort_errors()?;
-
- let stub_gen = || functor_stub(atom!("keysort"), 2);
- let list = self.machine_st.try_from_list(self.machine_st.registers[1], stub_gen)?;
-
- let mut key_pairs = Vec::with_capacity(list.len());
-
- for val in list {
- let key = self.machine_st.project_onto_key(val)?;
- key_pairs.push((key, val));
- }
-
- key_pairs.sort_by(|a1, a2| {
- compare_term_test!(self.machine_st, a1.0, a2.0).unwrap_or(Ordering::Less)
- });
-
- let key_pairs = key_pairs.into_iter().map(|kp| kp.1);
- let heap_addr = heap_loc_as_cell!(
- iter_to_heap_list(&mut self.machine_st.heap, key_pairs)
- );
-
- let r2 = self.machine_st.registers[2];
- unify_fn!(&mut self.machine_st, r2, heap_addr);
+ fn call_clause(&mut self, module_name: Atom, key: PredicateKey) -> CallResult {
+ let (name, arity) = key;
- return_from_clause!(self.machine_st.last_call, self.machine_st)
+ if module_name == atom!("user") {
+ if let Some(idx) = self.indices.code_dir.get(&(name, arity)).cloned() {
+ self.try_call(name, arity, idx.get())
+ } else {
+ Err(self.machine_st.throw_undefined_error(name, arity))
}
- &BuiltInClauseType::Is(r, ref at) => {
- let n1 = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
- let n2 = self.machine_st.get_number(at)?;
-
- match n2 {
- Number::Fixnum(n) => self.machine_st.unify_fixnum(n, n1),
- Number::Float(n) => {
- // TODO: argghh.. deal with it.
- let n = arena_alloc!(n, &mut self.machine_st.arena);
- self.machine_st.unify_f64(n, n1)
- }
- Number::Integer(n) => self.machine_st.unify_big_int(n, n1),
- Number::Rational(n) => self.machine_st.unify_rational(n, n1),
+ } else {
+ if let Some(module) = self.indices.modules.get(&module_name) {
+ if let Some(idx) = module.code_dir.get(&(name, arity)).cloned() {
+ self.try_call(name, arity, idx.get())
+ } else {
+ Err(self.machine_st.throw_undefined_error(name, arity))
}
+ } else {
+ let stub = functor_stub(name, arity);
+ let err = self.machine_st.module_resolution_error(module_name, name, arity);
- return_from_clause!(self.machine_st.last_call, self.machine_st)
+ Err(self.machine_st.error_form(err, stub))
}
}
}
#[inline(always)]
- fn call_clause_type(&mut self, module_name: Atom, key: PredicateKey) -> CallResult {
+ fn execute_clause(&mut self, module_name: Atom, key: PredicateKey) -> CallResult {
let (name, arity) = key;
- match ClauseType::from(name, arity) {
- ClauseType::BuiltIn(built_in) => {
- self.machine_st.setup_built_in_call(built_in);
- self.call_builtin(&built_in)?;
+ if module_name == atom!("user") {
+ if let Some(idx) = self.indices.code_dir.get(&(name, arity)).cloned() {
+ self.try_execute(name, arity, idx.get())
+ } else {
+ Err(self.machine_st.throw_undefined_error(name, arity))
}
- ClauseType::CallN => {
- self.machine_st.handle_internal_call_n(arity);
-
- if self.machine_st.fail {
- return Ok(());
- }
-
- self.machine_st.p = CodePtr::CallN(
- arity,
- self.machine_st.p.local(),
- self.machine_st.last_call,
- );
- }
- ClauseType::Inlined(inlined) => {
- self.execute_inlined(&inlined);
-
- if self.machine_st.last_call {
- self.machine_st.p = CodePtr::Local(self.machine_st.cp);
- }
- }
- ClauseType::Named(..) if module_name == atom!("user") => {
- return if let Some(idx) = self.indices.code_dir.get(&(name, arity)).cloned() {
- self.context_call(name, arity, idx)
+ } else {
+ if let Some(module) = self.indices.modules.get(&module_name) {
+ if let Some(idx) = module.code_dir.get(&(name, arity)).cloned() {
+ self.try_execute(name, arity, idx.get())
} else {
Err(self.machine_st.throw_undefined_error(name, arity))
- };
- }
- ClauseType::Named(..) => {
- return if let Some(module) = self.indices.modules.get(&module_name) {
- if let Some(idx) = module.code_dir.get(&(name, arity)).cloned() {
- self.context_call(name, arity, idx)
- } else {
- Err(self.machine_st.throw_undefined_error(name, arity))
- }
- } else {
- let stub = functor_stub(name, arity);
- let err = self.machine_st.module_resolution_error(module_name, name, arity);
-
- Err(self.machine_st.error_form(err, stub))
- };
- }
- ClauseType::System(_) => {
- let (name, arity) = key;
- let name = functor!(name);
-
- let stub = functor_stub(atom!("call"), arity + 1);
- let err = self.machine_st.type_error(ValidType::Callable, name);
+ }
+ } else {
+ let stub = functor_stub(name, arity);
+ let err = self.machine_st.module_resolution_error(module_name, name, arity);
- return Err(self.machine_st.error_form(err, stub));
+ Err(self.machine_st.error_form(err, stub))
}
}
-
- Ok(())
}
#[inline(always)]
fn call_n(&mut self, module_name: Atom, arity: usize) -> CallResult {
- if let Some(key) = self.machine_st.setup_call_n(arity) {
- self.call_clause_type(module_name, key)?;
- }
+ let key = self.machine_st.setup_call_n(arity)?;
+ self.call_clause(module_name, key)
+ }
- (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+ #[inline(always)]
+ fn execute_n(&mut self, module_name: Atom, arity: usize) -> CallResult {
+ let key = self.machine_st.setup_call_n(arity)?;
+ self.execute_clause(module_name, key)
}
#[inline(always)]
if let Some(&(_, b_cutoff, prev_block)) = self.machine_st.cont_pts.last() {
if self.machine_st.b < b_cutoff {
let (idx, arity) = if self.machine_st.block > prev_block {
- (dir_entry!(r_c_w_h), 0)
+ (r_c_w_h, 0)
} else {
self.machine_st.registers[1] = fixnum_as_cell!(
Fixnum::build_with(b_cutoff as i64)
);
- (dir_entry!(r_c_wo_h), 1)
+ (r_c_wo_h, 1)
};
- if self.machine_st.last_call {
- self.machine_st.execute_at_index(arity, idx);
- } else {
- self.machine_st.call_at_index(arity, idx);
- }
-
+ self.machine_st.call_at_index(arity, idx);
return true;
}
}
pub(super) fn unwind_trail(&mut self, a1: usize, a2: usize) {
// the sequence is reversed to respect the chronology of trail
- // additions, now that deleted attributes can be undeleted by
+ // additions now that deleted attributes can be undeleted by
// backtracking.
for i in (a1..a2).rev() {
let h = self.machine_st.trail[i].get_value() as usize;
use crate::atom_table::*;
-use crate::clause_types::*;
use crate::forms::*;
+use crate::instructions::*;
use crate::iterators::*;
use crate::machine::loader::*;
use crate::machine::machine_errors::*;
}
}
-/*
-fn setup_double_quotes(mut terms: Vec<Box<Term>>) -> Result<DoubleQuotes, CompilationError> {
- let dbl_quotes = *terms.pop().unwrap();
-
- match terms[0].as_ref() {
- Term::Literal(_, Literal::Atom(ref name, _))
- if name.as_str() == "double_quotes" => {
- match dbl_quotes {
- Term::Literal(_, Literal::Atom(name, _)) => {
- match name.as_str() {
- "atom" => Ok(DoubleQuotes::Atom),
- "chars" => Ok(DoubleQuotes::Chars),
- "codes" => Ok(DoubleQuotes::Codes),
- _ => Err(CompilationError::InvalidDoubleQuotesDecl),
- }
- }
- _ => {
- Err(CompilationError::InvalidDoubleQuotesDecl)
- }
- }
- },
- _ => {
- Err(CompilationError::InvalidDoubleQuotesDecl)
- }
- }
-}
- */
-
type UseModuleExport = (ModuleSource, IndexSet<ModuleExport>);
fn setup_qualified_import(
},
Term::Var(..) => Ok(QueryTerm::Clause(
Cell::default(),
- ClauseType::CallN,
+ ClauseType::CallN(1),
vec![term],
false,
)),
use core::marker::PhantomData;
-use crate::types::*;
-
-use crate::machine::machine_indices::*;
use crate::raw_block::*;
+use crate::types::*;
use std::mem;
use std::ops::{Index, IndexMut};
pub(crate) struct AndFramePrelude {
pub(crate) univ_prelude: FramePrelude,
pub(crate) e: usize,
- pub(crate) cp: LocalCodePtr,
- pub(crate) interrupt_cp: LocalCodePtr, // TODO: get rid of it!
+ pub(crate) cp: usize,
}
#[derive(Debug)]
pub(crate) struct OrFramePrelude {
pub(crate) univ_prelude: FramePrelude,
pub(crate) e: usize,
- pub(crate) cp: LocalCodePtr,
+ pub(crate) cp: usize,
pub(crate) b: usize,
- pub(crate) bp: LocalCodePtr,
+ pub(crate) bp: usize,
pub(crate) boip: u32,
pub(crate) biip: u32,
pub(crate) tr: usize,
use crate::arena::*;
use crate::atom_table::*;
-use crate::clause_types::*;
use crate::forms::*;
use crate::heap_iter::*;
use crate::heap_print::*;
use crate::instructions::*;
use crate::machine;
-use crate::machine::Machine;
+use crate::machine::{Machine, VERIFY_ATTR_INTERRUPT_LOC};
use crate::machine::code_walker::*;
use crate::machine::copier::*;
use crate::machine::heap::*;
use crate::machine::streams::*;
use crate::parser::char_reader::*;
use crate::parser::rug::Integer;
+use crate::parser::rug::rand::RandState;
use crate::read::*;
use crate::types::*;
use indexmap::IndexSet;
-use ref_thread_local::RefThreadLocal;
+use ref_thread_local::{RefThreadLocal, ref_thread_local};
use std::collections::BTreeSet;
use std::convert::TryFrom;
use std::fs;
use std::io::{ErrorKind, Read, Write};
use std::iter::{once, FromIterator};
+use std::mem;
use std::net::{TcpListener, TcpStream};
use std::num::NonZeroU32;
use std::ops::Sub;
use roxmltree;
use select;
+ref_thread_local! {
+ pub(crate) static managed RANDOM_STATE: RandState<'static> = RandState::new();
+}
+
pub(crate) fn get_key() -> KeyEvent {
let key;
enable_raw_mode().expect("failed to enable raw mode");
let deref_v = self.deref(value);
let store_v = self.store(deref_v);
- // let mut pstr_chars = 0;
+ let mut pstr_chars = 0;
let hare = read_heap_cell!(store_v,
(HeapCellValueTag::Lis, offset) => {
}
}
(HeapCellValueTag::PStrLoc, h) => {
- let (h_offset, _n) = pstr_loc_and_offset(&self.heap, h);
+ let (h_offset, n) = pstr_loc_and_offset(&self.heap, h);
+ let n = n.get_num() as usize;
+ let pstr = cell_as_string!(self.heap[h_offset]);
- if self.heap[h].get_tag() == HeapCellValueTag::PStr {
- h_offset+1
- } else {
+ pstr_chars = pstr.as_str_from(n).chars().count() - 1;
+
+ if self.heap[h].get_tag() == HeapCellValueTag::PStrOffset {
debug_assert!(self.heap[h].get_tag() == HeapCellValueTag::PStrOffset);
- h
+
+ if self.heap[h_offset].get_tag() == HeapCellValueTag::CStr {
+ return if pstr_chars + 1 <= max_steps {
+ CycleSearchResult::ProperList(pstr_chars + 1)
+ } else {
+ CycleSearchResult::UntouchedCStr(pstr.into(), max_steps)
+ };
+ }
+ }
+
+ if pstr_chars + 1 > max_steps {
+ return CycleSearchResult::PStrLocation(max_steps, h_offset);
}
+
+ h_offset+1
}
(HeapCellValueTag::PStrOffset) => {
unreachable!()
}
}
(HeapCellValueTag::Atom, (name, arity)) => {
- if name == atom!("[]") && arity == 0 {
- return CycleSearchResult::EmptyList;
+ return if name == atom!("[]") && arity == 0 {
+ CycleSearchResult::EmptyList
} else {
- return CycleSearchResult::NotList;
- }
+ CycleSearchResult::NotList
+ };
}
_ => {
return CycleSearchResult::NotList;
let mut brent_st = BrentAlgState::new(hare);
brent_st.power += 1; // advance a step.
- // brent_st.pstr_chars = pstr_chars;
+ brent_st.pstr_chars = pstr_chars;
loop {
if brent_st.num_steps() == max_steps {
}
}
- fn term_variables_under_max_depth(
- &mut self,
- term: HeapCellValue,
- max_depth: usize,
- list_of_vars: HeapCellValue,
- ) {
- let mut seen_set = IndexSet::new();
-
- {
- let mut iter = stackful_post_order_iter(&mut self.heap, term);
-
- while let Some(value) = iter.next() {
- if iter.parent_stack_len() >= max_depth {
- iter.pop_stack();
- continue;
- }
-
- let value = unmark_cell_bits!(value);
-
- if value.is_var() && !seen_set.contains(&value) {
- seen_set.insert(value);
- }
- }
- }
-
- let outcome = heap_loc_as_cell!(
- iter_to_heap_list(
- &mut self.heap,
- seen_set.into_iter().rev(),
- )
- );
-
- unify_fn!(*self, list_of_vars, outcome);
- }
-
fn finalize_skip_max_list(&mut self, n: usize, value: HeapCellValue) {
let target_n = self.registers[1];
self.unify_fixnum(Fixnum::build_with(n as i64), target_n);
Ok(())
}
-}
-impl MachineState {
+ fn term_variables_under_max_depth(
+ &mut self,
+ term: HeapCellValue,
+ max_depth: usize,
+ list_of_vars: HeapCellValue,
+ ) {
+ let mut seen_set = IndexSet::new();
+
+ {
+ let mut iter = stackful_post_order_iter(&mut self.heap, term);
+
+ while let Some(value) = iter.next() {
+ if iter.parent_stack_len() >= max_depth {
+ iter.pop_stack();
+ continue;
+ }
+
+ let value = unmark_cell_bits!(value);
+
+ if value.is_var() && !seen_set.contains(&value) {
+ seen_set.insert(value);
+ }
+ }
+ }
+
+ let outcome = heap_loc_as_cell!(
+ iter_to_heap_list(
+ &mut self.heap,
+ seen_set.into_iter().rev(),
+ )
+ );
+
+ unify_fn!(*self, list_of_vars, outcome);
+ }
+
#[inline]
- fn install_new_block(&mut self, value: HeapCellValue) -> usize {
+ pub(crate) fn install_new_block(&mut self, value: HeapCellValue) -> usize {
self.block = self.b;
self.unify_fixnum(Fixnum::build_with(self.block as i64), value);
self.block
}
- fn copy_findall_solution(&mut self, lh_offset: usize, copy_target: HeapCellValue) -> usize {
+ pub(crate) fn copy_findall_solution(&mut self, lh_offset: usize, copy_target: HeapCellValue) -> usize {
let threshold = self.lifted_heap.len() - lh_offset;
let mut copy_ball_term =
threshold + lh_offset + 2
}
- fn repl_redirect(&mut self, repl_code_ptr: REPLCodePtr) -> CallResult {
- let p = if self.last_call {
- self.cp
- } else {
- self.p.local() + 1
- };
-
- Ok(self.p = CodePtr::REPL(repl_code_ptr, p))
- }
-
#[inline(always)]
- fn truncate_if_no_lifted_heap_diff(
+ pub(crate) fn truncate_if_no_lifted_heap_diff(
&mut self,
addr_constr: impl Fn(usize) -> HeapCellValue,
) {
);
}
- fn get_next_db_ref(&self, indices: &IndexStore, db_ref: &DBRef) -> Option<DBRef> {
+ pub(crate) fn get_next_db_ref(&self, indices: &IndexStore, db_ref: &DBRef) -> Option<DBRef> {
match db_ref {
DBRef::NamedPred(name, arity) => {
let key = (*name, *arity);
return None;
}
- if SystemClauseType::from(*name, *arity).is_some() {
- continue;
- }
-
return Some(DBRef::NamedPred(*name, *arity));
}
}
None
}
- fn parse_number_from_string(
+ pub(crate) fn parse_number_from_string(
&mut self,
mut string: String,
indices: &IndexStore,
Ok(())
}
- fn call_continuation_chunk(&mut self, chunk: HeapCellValue, return_p: LocalCodePtr) -> LocalCodePtr {
+ pub(crate) fn call_continuation_chunk(&mut self, chunk: HeapCellValue, return_p: usize) -> usize {
let chunk = self.store(self.deref(chunk));
let s = chunk.get_value();
and_frame.prelude.e = prev_e;
and_frame.prelude.cp = return_p;
- self.p = CodePtr::Local(cp + 1);
+ self.p = cp + 1;
// adjust cut point to occur after call_continuation.
if num_cells > 0 {
}
self.e = e;
- self.p.local()
+ self.p
}
pub fn value_to_str_like(&mut self, value: HeapCellValue) -> Option<AtomOrString> {
// avoid allocating a String if possible ...
Some(AtomOrString::Atom(cstr_atom))
}
- (HeapCellValueTag::Atom, (atom, arity)) => { // TODO: Char??
+ (HeapCellValueTag::Atom, (atom, arity)) => {
if arity == 0 {
// ... likewise.
Some(AtomOrString::Atom(atom))
None
}
}
+ (HeapCellValueTag::Char, c) => {
+ Some(AtomOrString::Atom(self.atom_tbl.build_with(&c.to_string())))
+ }
_ => {
if value.is_constant() {
return None;
)
}
- fn codes_to_string(
+ pub(crate) fn codes_to_string(
&mut self,
addrs: impl Iterator<Item = HeapCellValue>,
stub_gen: impl Fn() -> FunctorStub,
}
impl Machine {
- pub(super) fn system_call(&mut self, ct: &SystemClauseType) -> CallResult {
- match ct {
- &SystemClauseType::BindFromRegister => {
- let reg = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
- let n = match Number::try_from(reg) {
- Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
- Ok(Number::Integer(n)) => n.to_usize(),
- _ => {
- unreachable!()
- }
- };
+ #[inline(always)]
+ pub(crate) fn is_reset_cont_marker(&self, p: usize) -> bool {
+ match &self.code[p] {
+ &Instruction::CallResetContinuationMarker(_) |
+ &Instruction::ExecuteResetContinuationMarker(_) => true,
+ _ => false
+ }
+ }
- if let Some(n) = n {
- if n <= MAX_ARITY {
- let target = self.machine_st.registers[n];
- let addr = self.machine_st.registers[1];
+ #[inline(always)]
+ pub(crate) fn bind_from_register(&mut self) {
+ let reg = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ let n = match Number::try_from(reg) {
+ Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
+ Ok(Number::Integer(n)) => n.to_usize(),
+ _ => {
+ unreachable!()
+ }
+ };
- unify_fn!(self.machine_st, addr, target);
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- }
+ if let Some(n) = n {
+ if n <= MAX_ARITY {
+ let target = self.machine_st.registers[n];
+ let addr = self.machine_st.registers[1];
- self.machine_st.fail = true;
+ unify_fn!(self.machine_st, addr, target);
+ return;
}
- &SystemClauseType::CurrentHostname => {
- match hostname::get().ok() {
- Some(host) => match host.to_str() {
- Some(host) => {
- let hostname = self.machine_st.atom_tbl.build_with(host);
+ }
- self.machine_st.unify_atom(
- hostname,
- self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
- );
+ self.machine_st.fail = true;
+ }
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- None => {}
- },
- None => {}
+ #[inline(always)]
+ pub(crate) fn current_hostname(&mut self) {
+ match hostname::get().ok() {
+ Some(host) => match host.to_str() {
+ Some(host) => {
+ let hostname = self.machine_st.atom_tbl.build_with(host);
+
+ self.machine_st.unify_atom(
+ hostname,
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
+ );
+
+ return;
}
+ None => {}
+ },
+ None => {}
+ }
- self.machine_st.fail = true;
- return Ok(());
- }
- &SystemClauseType::CurrentInput => {
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let stream = self.user_input;
+ self.machine_st.fail = true;
+ }
- if let Some(var) = addr.as_var() {
- self.machine_st.bind(var, stream_as_cell!(stream));
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
+ #[inline(always)]
+ pub(crate) fn current_input(&mut self) -> CallResult {
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let stream = self.user_input;
- read_heap_cell!(addr,
- (HeapCellValueTag::Cons, cons_ptr) => {
- match_untyped_arena_ptr!(cons_ptr,
- (ArenaHeaderTag::Stream, other_stream) => {
- self.machine_st.fail = stream != other_stream;
- }
- _ => {
- let stub = functor_stub(atom!("current_input"), 1);
- let err = self.machine_st.domain_error(DomainErrorType::Stream, addr);
+ if let Some(var) = addr.as_var() {
+ self.machine_st.bind(var, stream_as_cell!(stream));
+ return Ok(());
+ }
- return Err(self.machine_st.error_form(err, stub));
- }
- );
+ read_heap_cell!(addr,
+ (HeapCellValueTag::Cons, cons_ptr) => {
+ match_untyped_arena_ptr!(cons_ptr,
+ (ArenaHeaderTag::Stream, other_stream) => {
+ self.machine_st.fail = stream != other_stream;
}
_ => {
let stub = functor_stub(atom!("current_input"), 1);
}
);
}
- &SystemClauseType::CurrentOutput => {
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let stream = self.user_output;
+ _ => {
+ let stub = functor_stub(atom!("current_input"), 1);
+ let err = self.machine_st.domain_error(DomainErrorType::Stream, addr);
- if let Some(var) = addr.as_var() {
- self.machine_st.bind(var, stream_as_cell!(stream));
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
+ return Err(self.machine_st.error_form(err, stub));
+ }
+ );
- read_heap_cell!(addr,
- (HeapCellValueTag::Cons, cons_ptr) => {
- match_untyped_arena_ptr!(cons_ptr,
- (ArenaHeaderTag::Stream, other_stream) => {
- self.machine_st.fail = stream != other_stream;
- }
- _ => {
- let stub = functor_stub(atom!("current_output"), 1);
- let err = self.machine_st.domain_error(DomainErrorType::Stream, addr);
+ Ok(())
+ }
- return Err(self.machine_st.error_form(err, stub));
- }
- );
+ #[inline(always)]
+ pub(crate) fn current_output(&mut self) -> CallResult {
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let stream = self.user_output;
+
+ if let Some(var) = addr.as_var() {
+ self.machine_st.bind(var, stream_as_cell!(stream));
+ return Ok(());
+ }
+
+ read_heap_cell!(addr,
+ (HeapCellValueTag::Cons, cons_ptr) => {
+ match_untyped_arena_ptr!(cons_ptr,
+ (ArenaHeaderTag::Stream, other_stream) => {
+ self.machine_st.fail = stream != other_stream;
}
_ => {
let stub = functor_stub(atom!("current_output"), 1);
}
);
}
- &SystemClauseType::DirectoryFiles => {
- if let Some(dir) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- let path = std::path::Path::new(dir.as_str());
- let mut files = Vec::new();
+ _ => {
+ let stub = functor_stub(atom!("current_output"), 1);
+ let err = self.machine_st.domain_error(DomainErrorType::Stream, addr);
- if let Ok(entries) = fs::read_dir(path) {
- for entry in entries {
- if let Ok(entry) = entry {
- if let Some(name) = entry.file_name().to_str() {
- let name = self.machine_st.atom_tbl.build_with(name);
- files.push(atom_as_cstr_cell!(name));
+ return Err(self.machine_st.error_form(err, stub));
+ }
+ );
- continue;
- }
- }
+ Ok(())
+ }
- let stub = functor_stub(atom!("directory_files"), 2);
- let err = self.machine_st.representation_error(RepFlag::Character);
- let err = self.machine_st.error_form(err, stub);
+ #[inline(always)]
+ pub(crate) fn directory_files(&mut self) -> CallResult {
+ if let Some(dir) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ let path = std::path::Path::new(dir.as_str());
+ let mut files = Vec::new();
+
+ if let Ok(entries) = fs::read_dir(path) {
+ for entry in entries {
+ if let Ok(entry) = entry {
+ if let Some(name) = entry.file_name().to_str() {
+ let name = self.machine_st.atom_tbl.build_with(name);
+ files.push(atom_as_cstr_cell!(name));
- return Err(err);
+ continue;
}
+ }
- let files_list = heap_loc_as_cell!(
- iter_to_heap_list(&mut self.machine_st.heap, files.into_iter())
- );
+ let stub = functor_stub(atom!("directory_files"), 2);
+ let err = self.machine_st.representation_error(RepFlag::Character);
+ let err = self.machine_st.error_form(err, stub);
- unify!(self.machine_st, self.machine_st.registers[2], files_list);
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
+ return Err(err);
}
+ let files_list = heap_loc_as_cell!(
+ iter_to_heap_list(&mut self.machine_st.heap, files.into_iter())
+ );
+
+ unify!(self.machine_st, self.machine_st.registers[2], files_list);
+ return Ok(());
+ }
+ }
+
+ self.machine_st.fail = true;
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn file_size(&mut self) {
+ if let Some(file) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ let len = Number::arena_from(
+ fs::metadata(file.as_str()).unwrap().len(),
+ &mut self.machine_st.arena,
+ );
+
+ match len {
+ Number::Fixnum(n) => self.machine_st.unify_fixnum(n, self.machine_st.registers[2]),
+ Number::Integer(n) => self.machine_st.unify_big_int(n, self.machine_st.registers[2]),
+ _ => unreachable!(),
+ }
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn file_exists(&mut self) {
+ if let Some(file) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ let file_str = file.as_str();
+
+ if !std::path::Path::new(file_str).exists() || !fs::metadata(file_str).unwrap().is_file() {
self.machine_st.fail = true;
}
- &SystemClauseType::FileSize => {
- if let Some(file) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- let len = Number::arena_from(
- fs::metadata(file.as_str()).unwrap().len(),
- &mut self.machine_st.arena,
- );
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn directory_exists(&mut self) {
+ if let Some(dir) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ let dir_str = dir.as_str();
+
+ if !std::path::Path::new(dir_str).exists() || !fs::metadata(dir_str).unwrap().is_dir() {
+ self.machine_st.fail = true;
+ }
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
- match len {
- Number::Fixnum(n) => self.machine_st.unify_fixnum(n, self.machine_st.registers[2]),
- Number::Integer(n) => self.machine_st.unify_big_int(n, self.machine_st.registers[2]),
- _ => unreachable!(),
+ #[inline(always)]
+ pub(crate) fn file_time(&mut self) {
+ if let Some(file) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ let which = cell_as_atom!(self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[2]
+ )));
+
+ if let Ok(md) = fs::metadata(file.as_str()) {
+ if let Ok(time) = match which {
+ atom!("modification") => md.modified(),
+ atom!("access") => md.accessed(),
+ atom!("creation") => md.created(),
+ _ => {
+ unreachable!()
}
- } else {
- self.machine_st.fail = true;
+ } {
+ let chars_atom = self.systemtime_to_timestamp(time);
+
+ self.machine_st.unify_complete_string(
+ chars_atom,
+ self.machine_st.registers[3],
+ );
+
+ return;
}
}
- &SystemClauseType::FileExists => {
- if let Some(file) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- let file_str = file.as_str();
+ }
- if !std::path::Path::new(file_str).exists() || !fs::metadata(file_str).unwrap().is_file() {
- self.machine_st.fail = true;
- }
- } else {
+ self.machine_st.fail = true;
+ }
+
+ #[inline(always)]
+ pub(crate) fn directory_separator(&mut self) {
+ self.machine_st.unify_char(std::path::MAIN_SEPARATOR, self.machine_st.registers[1]);
+ }
+
+ #[inline(always)]
+ pub(crate) fn make_directory(&mut self) {
+ if let Some(dir) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ match fs::create_dir(dir.as_str()) {
+ Ok(_) => {}
+ _ => {
self.machine_st.fail = true;
}
}
- &SystemClauseType::DirectoryExists => {
- if let Some(dir) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- let dir_str = dir.as_str();
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
- if !std::path::Path::new(dir_str).exists()
- || !fs::metadata(dir_str).unwrap().is_dir()
- {
- self.machine_st.fail = true;
- return Ok(());
- }
- } else {
+ #[inline(always)]
+ pub(crate) fn make_directory_path(&mut self) {
+ if let Some(dir) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+
+ match fs::create_dir_all(dir.as_str()) {
+ Ok(_) => {}
+ _ => {
self.machine_st.fail = true;
}
}
- &SystemClauseType::DirectorySeparator => {
- self.machine_st.unify_char(std::path::MAIN_SEPARATOR, self.machine_st.registers[1]);
- }
- &SystemClauseType::MakeDirectory => {
- if let Some(dir) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- match fs::create_dir(dir.as_str()) {
- Ok(_) => {}
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
- } else {
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn delete_file(&mut self) {
+ if let Some(file) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ match fs::remove_file(file.as_str()) {
+ Ok(_) => {}
+ _ => {
self.machine_st.fail = true;
}
}
- &SystemClauseType::MakeDirectoryPath => {
- if let Some(dir) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ }
+ }
- match fs::create_dir_all(dir.as_str()) {
- Ok(_) => {}
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
- } else {
- self.machine_st.fail = true;
+ #[inline(always)]
+ pub(crate) fn rename_file(&mut self) {
+ if let Some(file) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ if let Some(renamed) = self.machine_st.value_to_str_like(self.machine_st.registers[2]) {
+ if fs::rename(file.as_str(), renamed.as_str()).is_ok() {
+ return;
}
}
- &SystemClauseType::DeleteFile => {
- if let Some(file) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- match fs::remove_file(file.as_str()) {
- Ok(_) => {}
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
+ }
+
+ self.machine_st.fail = true;
+ }
+
+ #[inline(always)]
+ pub(crate) fn delete_directory(&mut self) {
+ if let Some(dir) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ match fs::remove_dir(dir.as_str()) {
+ Ok(_) => {}
+ _ => {
+ self.machine_st.fail = true;
}
}
- &SystemClauseType::RenameFile => {
- if let Some(file) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- if let Some(renamed) = self.machine_st.value_to_str_like(self.machine_st.registers[2]) {
- if fs::rename(file.as_str(), renamed.as_str()).is_ok() {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- }
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn working_directory(&mut self) -> CallResult {
+ if let Ok(dir) = env::current_dir() {
+ let current = match dir.to_str() {
+ Some(d) => d,
+ _ => {
+ let stub = functor_stub(atom!("working_directory"), 2);
+ let err = self.machine_st.representation_error(RepFlag::Character);
+ let err = self.machine_st.error_form(err, stub);
+
+ return Err(err);
}
+ };
- self.machine_st.fail = true;
+ let current_atom = self.machine_st.atom_tbl.build_with(¤t);
+
+ self.machine_st.unify_complete_string(
+ current_atom,
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])),
+ );
+
+ if self.machine_st.fail {
+ return Ok(());
}
- &SystemClauseType::DeleteDirectory => {
- if let Some(dir) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- match fs::remove_dir(dir.as_str()) {
- Ok(_) => {}
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
+
+ if let Some(next) = self.machine_st.value_to_str_like(self.machine_st.registers[2]) {
+ if env::set_current_dir(std::path::Path::new(next.as_str())).is_ok() {
+ return Ok(());
}
}
- &SystemClauseType::WorkingDirectory => {
- if let Ok(dir) = env::current_dir() {
- let current = match dir.to_str() {
- Some(d) => d,
+ }
+
+ self.machine_st.fail = true;
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn path_canonical(&mut self) -> CallResult {
+ if let Some(path) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ match fs::canonicalize(path.as_str()) {
+ Ok(canonical) => {
+ let cs = match canonical.to_str() {
+ Some(s) => s,
_ => {
- let stub = functor_stub(atom!("working_directory"), 2);
+ let stub = functor_stub(atom!("path_canonical"), 2);
let err = self.machine_st.representation_error(RepFlag::Character);
let err = self.machine_st.error_form(err, stub);
}
};
- let current_atom = self.machine_st.atom_tbl.build_with(¤t);
+ let canonical_atom = self.machine_st.atom_tbl.build_with(cs);
self.machine_st.unify_complete_string(
- current_atom,
- self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])),
+ canonical_atom,
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
);
- if self.machine_st.fail {
- return Ok(());
- }
-
- if let Some(next) = self.machine_st.value_to_str_like(self.machine_st.registers[2]) {
- if env::set_current_dir(std::path::Path::new(next.as_str())).is_ok() {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- }
+ return Ok(());
+ }
+ _ => {
}
-
- self.machine_st.fail = true;
}
- &SystemClauseType::PathCanonical => {
- if let Some(path) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- match fs::canonicalize(path.as_str()) {
- Ok(canonical) => {
- let cs = match canonical.to_str() {
- Some(s) => s,
- _ => {
- let stub = functor_stub(atom!("path_canonical"), 2);
- let err = self.machine_st.representation_error(RepFlag::Character);
- let err = self.machine_st.error_form(err, stub);
-
- return Err(err);
- }
- };
+ }
+
+ self.machine_st.fail = true;
+ Ok(())
+ }
- let canonical_atom = self.machine_st.atom_tbl.build_with(cs);
+ #[inline(always)]
+ pub(crate) fn atom_chars(&mut self) {
+ let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- self.machine_st.unify_complete_string(
- canonical_atom,
- self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
- );
+ read_heap_cell!(a1,
+ (HeapCellValueTag::Char) => {
+ let h = self.machine_st.heap.len();
+
+ self.machine_st.heap.push(a1);
+ self.machine_st.heap.push(empty_list_as_cell!());
+
+ unify!(self.machine_st, self.machine_st.registers[2], list_loc_as_cell!(h));
+ }
+ (HeapCellValueTag::Atom, (name, arity)) => {
+ if arity == 0 {
+ self.machine_st.unify_complete_string(
+ name,
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
+ );
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+ (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
+ let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
+ if let Some(str_like) = self.machine_st.value_to_str_like(a2) {
+ let atom = match str_like {
+ AtomOrString::Atom(atom) => {
+ atom
}
- _ => {
+ AtomOrString::String(string) => {
+ self.machine_st.atom_tbl.build_with(&string)
}
- }
+ };
+
+ self.machine_st.bind(a1.as_var().unwrap(), atom_as_cell!(atom));
+ return;
}
self.machine_st.fail = true;
}
- &SystemClauseType::FileTime => {
- if let Some(file) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- let which = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])));
+ _ => {
+ unreachable!();
+ }
+ );
+ }
- if let Ok(md) = fs::metadata(file.as_str()) {
- if let Ok(time) = match which {
- atom!("modification") => md.modified(),
- atom!("access") => md.accessed(),
- atom!("creation") => md.created(),
- _ => {
- unreachable!()
- }
- } {
- let chars_atom = self.systemtime_to_timestamp(time);
+ #[inline(always)]
+ pub(crate) fn atom_codes(&mut self) -> CallResult {
+ let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- self.machine_st.unify_complete_string(
- chars_atom,
- self.machine_st.registers[3],
- );
+ read_heap_cell!(a1,
+ (HeapCellValueTag::Char, c) => {
+ let h = self.machine_st.heap.len();
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- }
- }
+ self.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(c as i64)));
+ self.machine_st.heap.push(empty_list_as_cell!());
- self.machine_st.fail = true;
+ unify!(self.machine_st, list_loc_as_cell!(h), self.machine_st.registers[2]);
}
- &SystemClauseType::AtomChars => {
- let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ (HeapCellValueTag::Atom, (name, arity)) => {
+ if arity == 0 {
+ let iter = name.chars()
+ .map(|c| fixnum_as_cell!(Fixnum::build_with(c as i64)));
- read_heap_cell!(a1,
- (HeapCellValueTag::Char) => {
- let h = self.machine_st.heap.len();
+ let h = iter_to_heap_list(&mut self.machine_st.heap, iter);
+ unify!(self.machine_st, heap_loc_as_cell!(h), self.machine_st.registers[2]);
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+ (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
+ let stub_gen = || functor_stub(atom!("atom_codes"), 2);
- self.machine_st.heap.push(a1);
- self.machine_st.heap.push(empty_list_as_cell!());
+ match self.machine_st.try_from_list(self.machine_st.registers[2], stub_gen) {
+ Ok(addrs) => {
+ let string = self.machine_st.codes_to_string(addrs.into_iter(), stub_gen)?;
+ let atom = self.machine_st.atom_tbl.build_with(&string);
- unify!(self.machine_st, self.machine_st.registers[2], list_loc_as_cell!(h));
+ self.machine_st.bind(a1.as_var().unwrap(), atom_as_cell!(atom));
}
- (HeapCellValueTag::Atom, (name, arity)) => {
- if arity == 0 {
- self.machine_st.unify_complete_string(
- name,
- self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
- );
- } else {
- self.machine_st.fail = true;
- }
+ Err(e) => {
+ return Err(e);
}
- (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
- let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ }
+ }
+ _ => {
+ unreachable!();
+ }
+ );
- if let Some(str_like) = self.machine_st.value_to_str_like(a2) {
- let atom = match str_like {
- AtomOrString::Atom(atom) => {
- atom
- }
- AtomOrString::String(string) => {
- self.machine_st.atom_tbl.build_with(&string)
- }
- };
+ Ok(())
+ }
- self.machine_st.bind(a1.as_var().unwrap(), atom_as_cell!(atom));
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
+ #[inline(always)]
+ pub(crate) fn atom_length(&mut self) {
+ let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- self.machine_st.fail = true;
- }
- _ => {
- unreachable!();
- }
- );
+ let len: i64 = read_heap_cell!(a1,
+ (HeapCellValueTag::Atom, (name, arity)) => {
+ if arity == 0 {
+ name.chars().count() as i64
+ } else {
+ self.machine_st.fail = true;
+ return;
+ }
}
- &SystemClauseType::AtomCodes => {
- let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
-
- read_heap_cell!(a1,
- (HeapCellValueTag::Char, c) => {
- let h = self.machine_st.heap.len();
+ (HeapCellValueTag::Char) => {
+ 1
+ }
+ _ => {
+ unreachable!()
+ }
+ );
- self.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(c as i64)));
- self.machine_st.heap.push(empty_list_as_cell!());
+ self.machine_st.unify_fixnum(
+ Fixnum::build_with(len),
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
+ );
+ }
- unify!(self.machine_st, list_loc_as_cell!(h), self.machine_st.registers[2]);
- }
- (HeapCellValueTag::Atom, (name, arity)) => {
- if arity == 0 {
- let iter = name.chars()
- .map(|c| fixnum_as_cell!(Fixnum::build_with(c as i64)));
+ #[inline(always)]
+ pub(crate) fn call_continuation(&mut self, last_call: bool) -> CallResult {
+ let stub_gen = || functor_stub(atom!("call_continuation"), 1);
+ let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+
+ match self.machine_st.try_from_list(a1, stub_gen) {
+ Err(e) => Err(e),
+ Ok(cont_chunks) => {
+ let mut return_p = if last_call {
+ self.machine_st.cp
+ } else {
+ self.machine_st.p + 1
+ };
- let h = iter_to_heap_list(&mut self.machine_st.heap, iter);
- unify!(self.machine_st, heap_loc_as_cell!(h), self.machine_st.registers[2]);
- } else {
- self.machine_st.fail = true;
- }
- }
- (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
- let stub_gen = || functor_stub(atom!("atom_codes"), 2);
+ self.machine_st.p = return_p;
- match self.machine_st.try_from_list(self.machine_st.registers[2], stub_gen) {
- Ok(addrs) => {
- let string = self.machine_st.codes_to_string(addrs.into_iter(), stub_gen)?;
- let atom = self.machine_st.atom_tbl.build_with(&string);
+ for chunk in cont_chunks.into_iter().rev() {
+ return_p = self.machine_st.call_continuation_chunk(chunk, return_p);
+ }
- self.machine_st.bind(a1.as_var().unwrap(), atom_as_cell!(atom));
- }
- Err(e) => {
- return Err(e);
- }
- }
- }
- _ => {
- unreachable!();
- }
- );
+ Ok(())
}
- &SystemClauseType::AtomLength => {
- let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ }
+ }
- let len: i64 = read_heap_cell!(a1,
- (HeapCellValueTag::Atom, (name, arity)) => {
- if arity == 0 {
- name.chars().count() as i64
- } else {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
- (HeapCellValueTag::Char) => {
- 1
- }
- _ => {
- unreachable!()
- }
- );
+ #[inline(always)]
+ pub(crate) fn chars_to_number(&mut self) -> CallResult {
+ let stub_gen = || functor_stub(atom!("number_chars"), 2);
+ let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+
+ if let Some(atom_or_string) = self.machine_st.value_to_str_like(a1) {
+ self.machine_st.parse_number_from_string(
+ atom_or_string.to_string(),
+ &self.indices,
+ stub_gen,
+ )?;
+ } else {
+ // a1 is a ground list at the call site within
+ // number_chars/2, so failure of value_to_str_like
+ // means the list contains a non-character.
+ let err = self.machine_st.type_error(ValidType::Character, a1);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
- self.machine_st.unify_fixnum(
- Fixnum::build_with(len),
- self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
- );
- }
- &SystemClauseType::CallContinuation => {
- let stub_gen = || functor_stub(atom!("call_continuation"), 1);
- let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ Ok(())
+ }
- match self.machine_st.try_from_list(a1, stub_gen) {
- Err(e) => return Err(e),
- Ok(cont_chunks) => {
- let mut return_p = if self.machine_st.last_call {
- self.machine_st.cp
- } else {
- self.machine_st.p.local() + 1
- };
+ #[inline(always)]
+ pub(crate) fn create_partial_string(&mut self) {
+ let atom = cell_as_atom!(
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
+ );
- self.machine_st.p = CodePtr::Local(return_p);
+ if atom == atom!("") {
+ self.machine_st.fail = true;
+ return;
+ }
- for chunk in cont_chunks.into_iter().rev() {
- return_p = self.machine_st.call_continuation_chunk(chunk, return_p);
- }
- }
- }
+ let pstr_h = self.machine_st.heap.len();
- return Ok(());
- }
- &SystemClauseType::CharsToNumber => {
- let stub_gen = || functor_stub(atom!("number_chars"), 2);
- let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ self.machine_st.heap.push(pstr_as_cell!(atom));
+ self.machine_st.heap.push(heap_loc_as_cell!(pstr_h+1));
- if let Some(atom_or_string) = self.machine_st.value_to_str_like(a1) {
- self.machine_st.parse_number_from_string(
- atom_or_string.to_string(),
- &self.indices,
- stub_gen,
- )?;
- } else {
- // a1 is a ground list at the call site within
- // number_chars/2, so failure of value_to_str_like
- // means the list contains a non-character.
- let err = self.machine_st.type_error(ValidType::Character, a1);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
- &SystemClauseType::CreatePartialString => {
- let atom = cell_as_atom!(
- self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
- );
+ unify!(self.machine_st, self.machine_st.registers[2], pstr_loc_as_cell!(pstr_h));
- if atom == atom!("") {
- self.machine_st.fail = true;
- return Ok(());
- }
+ if !self.machine_st.fail {
+ self.machine_st.bind(Ref::heap_cell(pstr_h+1), self.machine_st.registers[3]);
+ }
+ }
- let pstr_h = self.machine_st.heap.len();
+ #[inline(always)]
+ pub(crate) fn is_partial_string(&mut self) {
+ let value = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- self.machine_st.heap.push(pstr_as_cell!(atom));
- self.machine_st.heap.push(heap_loc_as_cell!(pstr_h+1));
+ let h = self.machine_st.heap.len();
+ self.machine_st.heap.push(value);
- unify!(self.machine_st, self.machine_st.registers[2], pstr_loc_as_cell!(pstr_h));
+ let mut iter = HeapPStrIter::new(&self.machine_st.heap, h);
- if !self.machine_st.fail {
- self.machine_st.bind(Ref::heap_cell(pstr_h+1), self.machine_st.registers[3]);
- }
- }
- &SystemClauseType::IsPartialString => {
- let value = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ while let Some(_) = iter.next() {}
- let h = self.machine_st.heap.len();
- self.machine_st.heap.push(value);
+ let at_end_of_pstr = iter.focus.is_var() || iter.at_string_terminator();
+ self.machine_st.fail = !at_end_of_pstr;
- let mut iter = HeapPStrIter::new(&self.machine_st.heap, h);
+ self.machine_st.heap.pop();
+ }
- while let Some(_) = iter.next() {}
+ #[inline(always)]
+ pub(crate) fn partial_string_tail(&mut self) {
+ let pstr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let at_end_of_pstr = iter.focus.is_var() || iter.at_string_terminator();
- self.machine_st.fail = !at_end_of_pstr;
+ read_heap_cell!(pstr,
+ (HeapCellValueTag::PStrLoc, h) => {
+ let (h, _) = pstr_loc_and_offset(&self.machine_st.heap, h);
- self.machine_st.heap.pop();
+ if HeapCellValueTag::CStr == self.machine_st.heap[h].get_tag() {
+ self.machine_st.unify_atom(
+ atom!("[]"),
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]))
+ );
+ } else {
+ unify_fn!(
+ self.machine_st,
+ heap_loc_as_cell!(h+1),
+ self.machine_st.registers[2]
+ );
+ }
}
- &SystemClauseType::PartialStringTail => {
- let pstr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
-
- read_heap_cell!(pstr,
- (HeapCellValueTag::PStrLoc, h) => {
- let (h, _) = pstr_loc_and_offset(&self.machine_st.heap, h);
-
- if HeapCellValueTag::CStr == self.machine_st.heap[h].get_tag() {
- self.machine_st.unify_atom(
- atom!("[]"),
- self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]))
- );
- } else {
- unify_fn!(
- self.machine_st,
- heap_loc_as_cell!(h+1),
- self.machine_st.registers[2]
- );
- }
- }
- (HeapCellValueTag::CStr) => {
- self.machine_st.unify_atom(
- atom!("[]"),
- self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]))
- );
- }
- (HeapCellValueTag::Lis, h) => {
- unify_fn!(
- self.machine_st,
- heap_loc_as_cell!(h+1),
- self.machine_st.registers[2]
- );
- }
- _ => {
- self.machine_st.fail = true;
- }
+ (HeapCellValueTag::CStr) => {
+ self.machine_st.unify_atom(
+ atom!("[]"),
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]))
);
}
- &SystemClauseType::PeekByte => {
- let stub_gen = || functor_stub(atom!("peek_byte"), 2);
-
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("peek_byte"),
- 2,
- )?;
-
- self.machine_st.check_stream_properties(
- stream,
- StreamType::Binary,
- Some(self.machine_st.registers[2]),
- atom!("peek_byte"),
- 2,
- )?;
-
- if stream.past_end_of_stream() {
- if EOFAction::Reset != stream.options().eof_action() {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- } else if self.machine_st.fail {
- return Ok(());
- }
- }
+ (HeapCellValueTag::Lis, h) => {
+ unify_fn!(
+ self.machine_st,
+ heap_loc_as_cell!(h+1),
+ self.machine_st.registers[2]
+ );
+ }
+ _ => {
+ self.machine_st.fail = true;
+ }
+ );
+ }
- if stream.at_end_of_stream() {
- stream.set_past_end_of_stream(true);
+ #[inline(always)]
+ pub(crate) fn peek_byte(&mut self) -> CallResult {
+ let stub_gen = || functor_stub(atom!("peek_byte"), 2);
+
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("peek_byte"),
+ 2,
+ )?;
+
+ self.machine_st.check_stream_properties(
+ stream,
+ StreamType::Binary,
+ Some(self.machine_st.registers[2]),
+ atom!("peek_byte"),
+ 2,
+ )?;
+
+ if stream.past_end_of_stream() {
+ if EOFAction::Reset != stream.options().eof_action() {
+ return Ok(());
+ } else if self.machine_st.fail {
+ return Ok(());
+ }
+ }
- self.machine_st.unify_fixnum(
- Fixnum::build_with(-1),
- self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
- );
+ if stream.at_end_of_stream() {
+ stream.set_past_end_of_stream(true);
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
+ self.machine_st.unify_fixnum(
+ Fixnum::build_with(-1),
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
+ );
- let addr = match self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])) {
- addr if addr.is_var() => addr,
- addr => match Number::try_from(addr) {
- Ok(Number::Integer(n)) => {
- if let Some(nb) = n.to_u8() {
- fixnum_as_cell!(Fixnum::build_with(nb as i64))
- } else {
- let err = self.machine_st.type_error(ValidType::InByte, addr);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
- Ok(Number::Fixnum(n)) => {
- if let Ok(nb) = u8::try_from(n.get_num()) {
- fixnum_as_cell!(Fixnum::build_with(nb as i64))
- } else {
- let err = self.machine_st.type_error(ValidType::InByte, addr);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
- _ => {
- let err = self.machine_st.type_error(ValidType::InByte, addr);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- },
- };
+ return Ok(());
+ }
- loop {
- match stream.peek_byte().map_err(|e| e.kind()) {
- Ok(b) => {
- self.machine_st.unify_fixnum(Fixnum::build_with(b as i64), addr);
- }
- Err(ErrorKind::PermissionDenied) => {
- self.machine_st.fail = true;
- break;
- }
- _ => {
- self.machine_st.eof_action(
- self.machine_st.registers[2],
- stream,
- atom!("peek_byte"),
- 2,
- )?;
-
- if EOFAction::Reset != stream.options().eof_action() {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- } else if self.machine_st.fail {
- return Ok(());
- }
- }
+ let addr = match self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])) {
+ addr if addr.is_var() => addr,
+ addr => match Number::try_from(addr) {
+ Ok(Number::Integer(n)) => {
+ if let Some(nb) = n.to_u8() {
+ fixnum_as_cell!(Fixnum::build_with(nb as i64))
+ } else {
+ let err = self.machine_st.type_error(ValidType::InByte, addr);
+ return Err(self.machine_st.error_form(err, stub_gen()));
}
}
- }
- &SystemClauseType::PeekChar => {
- let stub_gen = || functor_stub(atom!("peek_char"), 2);
-
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("peek_char"),
- 2,
- )?;
+ Ok(Number::Fixnum(n)) => {
+ if let Ok(nb) = u8::try_from(n.get_num()) {
+ fixnum_as_cell!(Fixnum::build_with(nb as i64))
+ } else {
+ let err = self.machine_st.type_error(ValidType::InByte, addr);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+ _ => {
+ let err = self.machine_st.type_error(ValidType::InByte, addr);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ },
+ };
- self.machine_st.check_stream_properties(
- stream,
- StreamType::Text,
- Some(self.machine_st.registers[2]),
- atom!("peek_char"),
- 2,
- )?;
+ loop {
+ match stream.peek_byte().map_err(|e| e.kind()) {
+ Ok(b) => {
+ self.machine_st.unify_fixnum(Fixnum::build_with(b as i64), addr);
+ }
+ Err(ErrorKind::PermissionDenied) => {
+ self.machine_st.fail = true;
+ break;
+ }
+ _ => {
+ self.machine_st.eof_action(
+ self.machine_st.registers[2],
+ stream,
+ atom!("peek_byte"),
+ 2,
+ )?;
- if stream.past_end_of_stream() {
if EOFAction::Reset != stream.options().eof_action() {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
+ break;
} else if self.machine_st.fail {
- return Ok(());
+ break;
}
}
+ }
+ }
- if stream.at_end_of_stream() {
- let end_of_file = atom!("end_of_file");
- stream.set_past_end_of_stream(true);
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn peek_char(&mut self) -> CallResult {
+ let stub_gen = || functor_stub(atom!("peek_char"), 2);
+
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("peek_char"),
+ 2,
+ )?;
+
+ self.machine_st.check_stream_properties(
+ stream,
+ StreamType::Text,
+ Some(self.machine_st.registers[2]),
+ atom!("peek_char"),
+ 2,
+ )?;
+
+ if stream.past_end_of_stream() {
+ if EOFAction::Reset != stream.options().eof_action() {
+ return Ok(());
+ } else if self.machine_st.fail {
+ return Ok(());
+ }
+ }
+
+ if stream.at_end_of_stream() {
+ let end_of_file = atom!("end_of_file");
+ stream.set_past_end_of_stream(true);
+
+ self.machine_st.unify_atom(
+ end_of_file,
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
+ );
- self.machine_st.unify_atom(end_of_file, self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])));
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
+ return Ok(());
+ }
+
+ let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+
+ let a2 = read_heap_cell!(a2,
+ (HeapCellValueTag::Char) => {
+ a2
+ }
+ (HeapCellValueTag::Atom, (name, arity)) => {
+ if arity == 0 {
+ if let Some(c) = name.as_char() {
+ char_as_cell!(c)
+ } else {
+ let err = self.machine_st.type_error(ValidType::InCharacter, a2);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ } else {
+ let err = self.machine_st.type_error(ValidType::InCharacter, a2);
+ return Err(self.machine_st.error_form(err, stub_gen()));
}
+ }
+ (HeapCellValueTag::Var | HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar) => {
+ a2
+ }
+ _ => {
+ let err = self.machine_st.type_error(ValidType::InCharacter, a2);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ );
- let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ loop {
+ match stream.peek_char().map(|result| result.map_err(|e| e.kind())) {
+ Some(Ok(d)) => {
+ self.machine_st.unify_char(d, a2);
+ break;
+ }
+ Some(Err(ErrorKind::PermissionDenied)) => {
+ self.machine_st.fail = true;
+ break;
+ }
+ _ => {
+ self.machine_st.eof_action(
+ self.machine_st.registers[2],
+ stream,
+ atom!("peek_char"),
+ 2,
+ )?;
- let a2 = read_heap_cell!(a2,
- (HeapCellValueTag::Char) => {
- a2
+ if EOFAction::Reset != stream.options().eof_action() {
+ break;
+ } else if self.machine_st.fail {
+ break;
}
- (HeapCellValueTag::Atom, (name, arity)) => {
- if arity == 0 {
- if let Some(c) = name.as_char() {
- char_as_cell!(c)
- } else {
- let err = self.machine_st.type_error(ValidType::InCharacter, a2);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
+ }
+ }
+ }
+
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn peek_code(&mut self) -> CallResult {
+ let stub_gen = || functor_stub(atom!("peek_code"), 2);
+
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("peek_code"),
+ 2,
+ )?;
+
+ self.machine_st.check_stream_properties(
+ stream,
+ StreamType::Text,
+ Some(self.machine_st.registers[2]),
+ atom!("peek_code"),
+ 2,
+ )?;
+
+ if stream.past_end_of_stream() {
+ if EOFAction::Reset != stream.options().eof_action() {
+ return Ok(());
+ } else if self.machine_st.fail {
+ return Ok(());
+ }
+ }
+
+ if stream.at_end_of_stream() {
+ let end_of_file = atom!("end_of_file");
+ stream.set_past_end_of_stream(true);
+
+ self.machine_st.unify_atom(
+ end_of_file,
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
+ );
+
+ return Ok(());
+ }
+
+ let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+
+ let addr = read_heap_cell!(a2,
+ (HeapCellValueTag::Var | HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar) => {
+ a2
+ }
+ _ => {
+ match Number::try_from(a2) {
+ Ok(Number::Integer(n)) => {
+ let n = n
+ .to_u32()
+ .and_then(|n| std::char::from_u32(n).and_then(|_| Some(n)));
+
+ if let Some(n) = n {
+ fixnum_as_cell!(Fixnum::build_with(n as i64))
} else {
- let err = self.machine_st.type_error(ValidType::InCharacter, a2);
+ let err = self.machine_st.representation_error(RepFlag::InCharacterCode);
return Err(self.machine_st.error_form(err, stub_gen()));
}
}
- (HeapCellValueTag::Var | HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar) => {
- a2
+ Ok(Number::Fixnum(n)) => {
+ let n = u32::try_from(n.get_num())
+ .ok()
+ .and_then(|n| std::char::from_u32(n).and_then(|_| Some(n)));
+
+ if let Some(n) = n {
+ fixnum_as_cell!(Fixnum::build_with(n as i64))
+ } else {
+ let err = self.machine_st.representation_error(RepFlag::InCharacterCode);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
}
_ => {
- let err = self.machine_st.type_error(ValidType::InCharacter, a2);
+ let err = self.machine_st.type_error(ValidType::Integer, self.machine_st.registers[2]);
return Err(self.machine_st.error_form(err, stub_gen()));
}
- );
-
- loop {
- match stream.peek_char().map(|result| result.map_err(|e| e.kind())) {
- Some(Ok(d)) => {
- self.machine_st.unify_char(d, a2);
- break;
- }
- Some(Err(ErrorKind::PermissionDenied)) => {
- self.machine_st.fail = true;
- break;
- }
- _ => {
- self.machine_st.eof_action(
- self.machine_st.registers[2],
- stream,
- atom!("peek_char"),
- 2,
- )?;
-
- if EOFAction::Reset != stream.options().eof_action() {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- } else if self.machine_st.fail {
- return Ok(());
- }
- }
- }
}
}
- &SystemClauseType::PeekCode => {
- let stub_gen = || functor_stub(atom!("peek_code"), 2);
+ );
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("peek_code"),
- 2,
- )?;
+ loop {
+ let result = stream.peek_char();
- self.machine_st.check_stream_properties(
- stream,
- StreamType::Text,
- Some(self.machine_st.registers[2]),
- atom!("peek_code"),
- 2,
- )?;
+ match result.map(|result| result.map_err(|e| e.kind())) {
+ Some(Ok(c)) => {
+ self.machine_st.unify_fixnum(Fixnum::build_with(c as i64), addr);
+ break;
+ }
+ Some(Err(ErrorKind::PermissionDenied)) => {
+ self.machine_st.fail = true;
+ break;
+ }
+ _ => {
+ self.machine_st.eof_action(
+ self.machine_st.registers[2],
+ stream,
+ atom!("peek_code"),
+ 2,
+ )?;
- if stream.past_end_of_stream() {
if EOFAction::Reset != stream.options().eof_action() {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
+ break;
} else if self.machine_st.fail {
- return Ok(());
+ break;
}
}
+ }
+ }
- if stream.at_end_of_stream() {
- let end_of_file = atom!("end_of_file");
- stream.set_past_end_of_stream(true);
+ return Ok(());
+ }
- self.machine_st.unify_atom(end_of_file, self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])));
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
+ #[inline(always)]
+ pub(crate) fn number_to_chars(&mut self) {
+ let n = self.machine_st.registers[1];
+ let chs = self.machine_st.registers[2];
+
+ let n = self.machine_st.store(self.machine_st.deref(n));
+
+ let string = match Number::try_from(n) {
+ Ok(Number::Float(OrderedFloat(n))) => {
+ format!("{0:<20?}", n)
+ }
+ Ok(Number::Fixnum(n)) => n.get_num().to_string(),
+ Ok(Number::Integer(n)) => n.to_string(),
+ Ok(Number::Rational(r)) => {
+ // n has already been confirmed as an integer, and
+ // internally, Rational is assumed reduced, so its denominator
+ // must be 1.
+ r.numer().to_string()
+ }
+ _ => {
+ unreachable!()
+ }
+ };
+
+ let chars_atom = self.machine_st.atom_tbl.build_with(&string.trim());
+ self.machine_st.unify_complete_string(chars_atom, self.machine_st.store(self.machine_st.deref(chs)));
+ }
+
+ #[inline(always)]
+ pub(crate) fn number_to_codes(&mut self) {
+ let n = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let chs = self.machine_st.registers[2];
+
+ let string = match Number::try_from(n) {
+ Ok(Number::Float(OrderedFloat(n))) => {
+ format!("{0:<20?}", n)
+ }
+ Ok(Number::Fixnum(n)) => n.get_num().to_string(),
+ Ok(Number::Integer(n)) => n.to_string(),
+ Ok(Number::Rational(r)) => {
+ // n has already been confirmed as an integer, and
+ // internally, Rational is assumed reduced, so its
+ // denominator must be 1.
+ r.numer().to_string()
+ }
+ _ => {
+ unreachable!()
+ }
+ };
+
+ let codes = string.trim().chars().map(|c| {
+ fixnum_as_cell!(Fixnum::build_with(c as i64))
+ });
+
+ let h = iter_to_heap_list(&mut self.machine_st.heap, codes);
+ unify!(self.machine_st, heap_loc_as_cell!(h), chs);
+ }
+
+ #[inline(always)]
+ pub(crate) fn codes_to_number(&mut self) -> CallResult {
+ let stub_gen = || functor_stub(atom!("number_codes"), 2);
+
+ match self.machine_st.try_from_list(self.machine_st.registers[1], stub_gen) {
+ Err(e) => {
+ return Err(e);
+ }
+ Ok(addrs) => {
+ let string = self.machine_st.codes_to_string(addrs.into_iter(), stub_gen)?;
+ self.machine_st.parse_number_from_string(string, &self.indices, stub_gen)?;
+ }
+ }
+
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn lifted_heap_length(&mut self) {
+ let a1 = self.machine_st.registers[1];
+ let lh_len = Fixnum::build_with(self.machine_st.lifted_heap.len() as i64);
+
+ self.machine_st.unify_fixnum(lh_len, a1);
+ }
+
+ #[inline(always)]
+ pub(crate) fn char_code(&mut self) -> CallResult {
+ let stub_gen = || functor_stub(atom!("char_code"), 2);
+ let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let c = read_heap_cell!(a1,
+ (HeapCellValueTag::Atom, (name, _arity)) => {
+ name.as_char().unwrap()
+ }
+ (HeapCellValueTag::Char, c) => {
+ c
+ }
+ _ => {
let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
- let addr = read_heap_cell!(a2,
- (HeapCellValueTag::Var | HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar) => {
- a2
- }
- _ => {
- match Number::try_from(a2) {
- Ok(Number::Integer(n)) => {
- let n = n
- .to_u32()
- .and_then(|n| std::char::from_u32(n).and_then(|_| Some(n)));
-
- if let Some(n) = n {
- fixnum_as_cell!(Fixnum::build_with(n as i64))
- } else {
- let err = self.machine_st.representation_error(RepFlag::InCharacterCode);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
- Ok(Number::Fixnum(n)) => {
- let n = u32::try_from(n.get_num())
- .ok()
- .and_then(|n| std::char::from_u32(n).and_then(|_| Some(n)));
-
- if let Some(n) = n {
- fixnum_as_cell!(Fixnum::build_with(n as i64))
- } else {
- let err = self.machine_st.representation_error(RepFlag::InCharacterCode);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
+ match Number::try_from(a2) {
+ Ok(Number::Integer(n)) => {
+ let c = match n.to_u32().and_then(std::char::from_u32) {
+ Some(c) => c,
_ => {
- let err = self.machine_st.type_error(ValidType::Integer, self.machine_st.registers[2]);
+ let err = self.machine_st.representation_error(RepFlag::CharacterCode);
return Err(self.machine_st.error_form(err, stub_gen()));
}
- }
- }
- );
-
- loop {
- let result = stream.peek_char();
+ };
- match result.map(|result| result.map_err(|e| e.kind())) {
- Some(Ok(c)) => {
- self.machine_st.unify_fixnum(Fixnum::build_with(c as i64), addr);
- break;
- }
- Some(Err(ErrorKind::PermissionDenied)) => {
- self.machine_st.fail = true;
- break;
- }
- _ => {
- self.machine_st.eof_action(
- self.machine_st.registers[2],
- stream,
- atom!("peek_code"),
- 2,
- )?;
-
- if EOFAction::Reset != stream.options().eof_action() {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- } else if self.machine_st.fail {
- return Ok(());
+ self.machine_st.unify_char(c, a2);
+ return Ok(());
+ }
+ Ok(Number::Fixnum(n)) => {
+ match u32::try_from(n.get_num()) {
+ Ok(n) => {
+ if let Some(c) = std::char::from_u32(n) {
+ self.machine_st.unify_char(c, a1);
+ return Ok(());
+ }
}
+ _ => {}
}
+
+ let err = self.machine_st.representation_error(RepFlag::CharacterCode);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ _ => {
+ self.machine_st.fail = true;
+ return Ok(());
}
}
}
- &SystemClauseType::NumberToChars => {
- let n = self.machine_st.registers[1];
- let chs = self.machine_st.registers[2];
+ );
+
+ self.machine_st.unify_fixnum(
+ Fixnum::build_with(c as i64),
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
+ );
+
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn char_type(&mut self) {
+ let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+
+ let c = read_heap_cell!(a1,
+ (HeapCellValueTag::Char, c) => {
+ c
+ }
+ (HeapCellValueTag::Atom, (name, _arity)) => {
+ name.as_char().unwrap()
+ }
+ _ => {
+ unreachable!()
+ }
+ );
+
+ let chars = cell_as_atom!(a2);
+ self.machine_st.fail = true; // This predicate fails by default.
+
+ macro_rules! macro_check {
+ ($id:ident, $name:expr) => {
+ if $id!(c) && chars == $name {
+ self.machine_st.fail = false;
+ return;
+ }
+ };
+ }
+
+ macro_rules! method_check {
+ ($id:ident, $name:expr) => {
+ if c.$id() && chars == $name {
+ self.machine_st.fail = false;
+ return;
+ }
+ };
+ }
+
+ macro_check!(alpha_char, atom!("alpha"));
+ method_check!(is_alphabetic, atom!("alphabetic"));
+ method_check!(is_alphanumeric, atom!("alphanumeric"));
+ macro_check!(alpha_numeric_char, atom!("alnum"));
+ method_check!(is_ascii, atom!("ascii"));
+ method_check!(is_ascii_punctuation, atom!("ascii_ponctuaction"));
+ method_check!(is_ascii_graphic, atom!("ascii_graphic"));
+ // macro_check!(backslash_char, atom!("backslash"));
+ // macro_check!(back_quote_char, atom!("back_quote"));
+ macro_check!(binary_digit_char, atom!("binary_digit"));
+ // macro_check!(capital_letter_char, atom!("upper"));
+ // macro_check!(comment_1_char, "comment_1");
+ // macro_check!(comment_2_char, "comment_2");
+ method_check!(is_control, atom!("control"));
+ // macro_check!(cut_char, atom!("cut"));
+ macro_check!(decimal_digit_char, atom!("decimal_digit"));
+ // macro_check!(decimal_point_char, atom!("decimal_point"));
+ // macro_check!(double_quote_char, atom!("double_quote"));
+ macro_check!(exponent_char, atom!("exponent"));
+ macro_check!(graphic_char, atom!("graphic"));
+ macro_check!(graphic_token_char, atom!("graphic_token"));
+ macro_check!(hexadecimal_digit_char, atom!("hexadecimal_digit"));
+ macro_check!(layout_char, atom!("layout"));
+ method_check!(is_lowercase, atom!("lower"));
+ macro_check!(meta_char, atom!("meta"));
+ // macro_check!(new_line_char, atom!("new_line"));
+ method_check!(is_numeric, atom!("numeric"));
+ macro_check!(octal_digit_char, atom!("octal_digit"));
+ macro_check!(octet_char, atom!("octet"));
+ macro_check!(prolog_char, atom!("prolog"));
+ // macro_check!(semicolon_char, atom!("semicolon"));
+ macro_check!(sign_char, atom!("sign"));
+ // macro_check!(single_quote_char, atom!("single_quote"));
+ // macro_check!(small_letter_char, atom!("lower"));
+ macro_check!(solo_char, atom!("solo"));
+ // macro_check!(space_char, atom!("space"));
+ macro_check!(symbolic_hexadecimal_char, atom!("symbolic_hexadecimal"));
+ macro_check!(symbolic_control_char, atom!("symbolic_control"));
+ method_check!(is_uppercase, atom!("upper"));
+ // macro_check!(variable_indicator_char, atom!("variable_indicator"));
+ method_check!(is_whitespace, atom!("whitespace"));
+ }
+
+ #[inline(always)]
+ pub(crate) fn check_cut_point(&mut self) {
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let old_b = cell_as_fixnum!(addr).get_num() as usize;
+
+ let prev_b = self.machine_st.stack.index_or_frame(self.machine_st.b).prelude.b;
+ let prev_b = self.machine_st.stack.index_or_frame(prev_b).prelude.b;
+
+ if prev_b > old_b {
+ self.machine_st.fail = true;
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn copy_term_without_attr_vars(&mut self) {
+ self.machine_st.copy_term(AttrVarPolicy::StripAttributes);
+ }
+
+ #[inline(always)]
+ pub(crate) fn fetch_global_var(&mut self) {
+ let key = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])));
+ let addr = self.machine_st.registers[2];
+
+ match self.indices.global_variables.get_mut(&key) {
+ Some((ref ball, ref mut loc)) => match loc {
+ Some(value_loc) => {
+ unify_fn!(self.machine_st, addr, *value_loc);
+ }
+ None if !ball.stub.is_empty() => {
+ let h = self.machine_st.heap.len();
+ let stub = ball.copy_and_align(h);
+
+ self.machine_st.heap.extend(stub.into_iter());
+
+ unify_fn!(self.machine_st, addr, heap_loc_as_cell!(h));
+
+ if !self.machine_st.fail {
+ *loc = Some(heap_loc_as_cell!(h));
+ self.machine_st.trail(TrailRef::BlackboardEntry(key));
+ }
+ }
+ _ => self.machine_st.fail = true,
+ },
+ None => self.machine_st.fail = true,
+ };
+ }
+
+ #[inline(always)]
+ pub(crate) fn put_code(&mut self) -> CallResult {
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("put_code"),
+ 2,
+ )?;
+
+ self.machine_st.check_stream_properties(
+ stream,
+ StreamType::Text,
+ None,
+ atom!("put_code"),
+ 2,
+ )?;
+
+ let stub_gen = || functor_stub(atom!("put_code"), 2);
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+
+ if addr.is_var() {
+ let err = self.machine_st.instantiation_error();
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ } else {
+ match Number::try_from(addr) {
+ Ok(Number::Integer(n)) => {
+ if let Some(c) = n.to_u32().and_then(|c| char::try_from(c).ok()) {
+ write!(&mut stream, "{}", c).unwrap();
+ return Ok(());
+ }
+ }
+ Ok(Number::Fixnum(n)) => {
+ let n = n.get_num();
+
+ if let Some(c) = u32::try_from(n).ok().and_then(|c| char::from_u32(c)) {
+ write!(&mut stream, "{}", c).unwrap();
+ return Ok(());
+ }
+ }
+ _ => {
+ let err = self.machine_st.type_error(ValidType::Integer, addr);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+
+ let err = self.machine_st.representation_error(RepFlag::CharacterCode);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn put_char(&mut self) -> CallResult {
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("put_char"),
+ 2,
+ )?;
+
+ self.machine_st.check_stream_properties(
+ stream,
+ StreamType::Text,
+ None,
+ atom!("put_char"),
+ 2,
+ )?;
+
+ let stub_gen = || functor_stub(atom!("put_char"), 2);
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+
+ if addr.is_var() {
+ let err = self.machine_st.instantiation_error();
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ } else {
+ read_heap_cell!(addr,
+ (HeapCellValueTag::Atom, (name, _arity)) => {
+ let c = name.as_char().unwrap();
+ write!(&mut stream, "{}", c).unwrap();
+ return Ok(());
+ }
+ (HeapCellValueTag::Char, c) => {
+ write!(&mut stream, "{}", c).unwrap();
+ return Ok(());
+ }
+ _ => {
+ }
+ );
+
+ let err = self.machine_st.type_error(ValidType::Character, addr);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn put_chars(&mut self) -> CallResult {
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("$put_chars"),
+ 2,
+ )?;
+
+ let mut bytes = Vec::new();
+ let stub_gen = || functor_stub(atom!("$put_chars"), 2);
+
+ if let Some(string) = self.machine_st.value_to_str_like(self.machine_st.registers[2]) {
+ if stream.options().stream_type() == StreamType::Binary {
+ for c in string.as_str().chars() {
+ if c as u32 > 255 {
+ let err = self.machine_st.type_error(ValidType::Byte, char_as_cell!(c));
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+
+ bytes.push(c as u8);
+ }
+ } else {
+ bytes = string.as_str().bytes().collect();
+ }
+
+ match stream.write_all(&bytes) {
+ Ok(_) => {
+ }
+ _ => {
+ let addr = stream_as_cell!(stream);
+ let err = self.machine_st.existence_error(ExistenceError::Stream(addr));
+
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+ } else {
+ self.machine_st.fail = true;
+ }
+
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn put_byte(&mut self) -> CallResult {
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("put_byte"),
+ 2,
+ )?;
+
+ self.machine_st.check_stream_properties(
+ stream,
+ StreamType::Binary,
+ None,
+ atom!("put_byte"),
+ 2,
+ )?;
+
+ let stub_gen = || functor_stub(atom!("put_byte"), 2);
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+
+ if addr.is_var() {
+ let err = self.machine_st.instantiation_error();
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ } else {
+ match Number::try_from(addr) {
+ Ok(Number::Integer(n)) => {
+ if let Some(nb) = n.to_u8() {
+ match stream.write(&mut [nb]) {
+ Ok(1) => {
+ return Ok(());
+ }
+ _ => {
+ let err = self.machine_st.existence_error(
+ ExistenceError::Stream(stream_as_cell!(stream))
+ );
+
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+ }
+ }
+ Ok(Number::Fixnum(n)) => {
+ if let Ok(nb) = u8::try_from(n.get_num()) {
+ match stream.write(&mut [nb]) {
+ Ok(1) => {
+ return Ok(());
+ }
+ _ => {
+ let err = self.machine_st.existence_error(
+ ExistenceError::Stream(stream_as_cell!(stream))
+ );
+
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+ }
+ }
+ _ => {
+ }
+ }
+ }
+
+ let err = self.machine_st.type_error(ValidType::Byte, self.machine_st.registers[2]);
+ Err(self.machine_st.error_form(err, stub_gen()))
+ }
+
+ #[inline(always)]
+ pub(crate) fn get_byte(&mut self) -> CallResult {
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("get_byte"),
+ 2,
+ )?;
+
+ self.machine_st.check_stream_properties(
+ stream,
+ StreamType::Binary,
+ Some(self.machine_st.registers[2]),
+ atom!("get_byte"),
+ 2,
+ )?;
+
+ if stream.past_end_of_stream() {
+ self.machine_st.eof_action(self.machine_st.registers[2], stream, atom!("get_byte"), 2)?;
+
+ if EOFAction::Reset != stream.options().eof_action() {
+ return Ok(());
+ } else if self.machine_st.fail {
+ return Ok(());
+ }
+ }
+
+ let stub_gen = || functor_stub(atom!("get_byte"), 2);
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+
+ let addr = if addr.is_var() {
+ addr
+ } else {
+ match Number::try_from(addr) {
+ Ok(Number::Integer(n)) => {
+ if let Some(nb) = n.to_u8() {
+ fixnum_as_cell!(Fixnum::build_with(nb as i64))
+ } else {
+ let err = self.machine_st.type_error(ValidType::InByte, addr);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+ Ok(Number::Fixnum(n)) => {
+ if let Ok(nb) = u8::try_from(n.get_num()) {
+ fixnum_as_cell!(Fixnum::build_with(nb as i64))
+ } else {
+ let err = self.machine_st.type_error(ValidType::InByte, addr);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+ _ => {
+ let err = self.machine_st.type_error(ValidType::InByte, addr);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+ };
+
+ loop {
+ let mut b = [0u8; 1];
+
+ match stream.read(&mut b) {
+ Ok(1) => {
+ self.machine_st.unify_fixnum(Fixnum::build_with(b[0] as i64), addr);
+ break;
+ }
+ _ => {
+ stream.set_past_end_of_stream(true);
+ self.machine_st.unify_fixnum(Fixnum::build_with(-1), self.machine_st.registers[2]);
+ break;
+ }
+ }
+ }
+
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn get_char(&mut self) -> CallResult {
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("get_char"),
+ 2,
+ )?;
+
+ self.machine_st.check_stream_properties(
+ stream,
+ StreamType::Text,
+ Some(self.machine_st.registers[2]),
+ atom!("get_char"),
+ 2,
+ )?;
+
+ if stream.past_end_of_stream() {
+ if EOFAction::Reset != stream.options().eof_action() {
+ return Ok(());
+ } else if self.machine_st.fail {
+ return Ok(());
+ }
+ }
+
+ if stream.at_end_of_stream() {
+ let end_of_file = atom!("end_of_file");
+ stream.set_past_end_of_stream(true);
+
+ self.machine_st.unify_atom(
+ end_of_file,
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]))
+ );
+
+ return Ok(());
+ }
+
+ let stub_gen = || functor_stub(atom!("get_char"), 2);
+ let mut iter = self.machine_st.open_parsing_stream(stream, atom!("get_char"), 2)?;
+
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+
+ let addr = if addr.is_var() {
+ addr
+ } else {
+ read_heap_cell!(addr,
+ (HeapCellValueTag::Atom, (atom, _arity)) => {
+ char_as_cell!(atom.as_char().unwrap())
+ }
+ (HeapCellValueTag::Char) => {
+ addr
+ }
+ _ => {
+ let err = self.machine_st.type_error(ValidType::InCharacter, addr);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ )
+ };
+
+ loop {
+ let result = iter.read_char();
+
+ match result {
+ Some(Ok(c)) => {
+ self.machine_st.unify_char(c, addr);
+ break;
+ }
+ _ => {
+ self.machine_st.eof_action(
+ self.machine_st.registers[2],
+ stream,
+ atom!("get_char"),
+ 2,
+ )?;
+
+ if EOFAction::Reset != stream.options().eof_action() {
+ break;
+ } else if self.machine_st.fail {
+ break;
+ }
+ }
+ }
+ }
+
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn get_n_chars(&mut self) -> CallResult {
+ let stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("get_n_chars"),
+ 3,
+ )?;
+
+ let num = match Number::try_from(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]))) {
+ Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).unwrap(),
+ Ok(Number::Integer(n)) => match n.to_usize() {
+ Some(u) => u,
+ _ => {
+ self.machine_st.fail = true;
+ return Ok(());
+ }
+ },
+ _ => {
+ unreachable!()
+ }
+ };
+
+ let mut string = String::new();
+
+ if stream.options().stream_type() == StreamType::Binary {
+ let mut buf = vec![];
+ let mut chunk = stream.take(num as u64);
+
+ chunk.read_to_end(&mut buf).ok();
+
+ for c in buf {
+ string.push(c as char);
+ }
+ } else {
+ let mut iter = self.machine_st.open_parsing_stream(stream, atom!("get_n_chars"), 2)?;
+
+ for _ in 0..num {
+ let result = iter.read_char();
+
+ match result {
+ Some(Ok(c)) => {
+ string.push(c);
+ }
+ _ => {
+ break;
+ }
+ }
+ }
+ };
+
+ let atom = self.machine_st.atom_tbl.build_with(&string);
+ self.machine_st.unify_complete_string(atom, self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3])));
+
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn get_code(&mut self) -> CallResult {
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("get_code"),
+ 2,
+ )?;
+
+ self.machine_st.check_stream_properties(
+ stream,
+ StreamType::Text,
+ Some(self.machine_st.registers[2]),
+ atom!("get_code"),
+ 2,
+ )?;
+
+ if stream.past_end_of_stream() {
+ if EOFAction::Reset != stream.options().eof_action() {
+ return Ok(());
+ } else if self.machine_st.fail {
+ return Ok(());
+ }
+ }
+
+ if stream.at_end_of_stream() {
+ let end_of_file = atom!("end_of_file");
+ stream.set_past_end_of_stream(true);
+
+ self.machine_st.unify_atom(
+ end_of_file,
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
+ );
+
+ return Ok(());
+ }
+
+ let stub_gen = || functor_stub(atom!("get_code"), 2);
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+
+ let addr = if addr.is_var() {
+ addr
+ } else {
+ match Number::try_from(addr) {
+ Ok(Number::Integer(n)) => {
+ let n = n
+ .to_u32()
+ .and_then(|n| std::char::from_u32(n));
+
+ if let Some(n) = n {
+ fixnum_as_cell!(Fixnum::build_with(n as i64))
+ } else {
+ let err = self.machine_st.representation_error(RepFlag::InCharacterCode);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+ Ok(Number::Fixnum(n)) => {
+ let nf = u32::try_from(n.get_num())
+ .ok()
+ .and_then(|n| std::char::from_u32(n));
+
+ if nf.is_some() {
+ fixnum_as_cell!(n)
+ } else {
+ let err = self.machine_st.representation_error(RepFlag::InCharacterCode);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+ _ => {
+ let err = self.machine_st.type_error(ValidType::Integer, self.machine_st.registers[2]);
+ return Err(self.machine_st.error_form(err, stub_gen()));
+ }
+ }
+ };
+
+ let mut iter = self.machine_st.open_parsing_stream(stream.clone(), atom!("get_code"), 2)?;
+
+ loop {
+ let result = iter.read_char();
+
+ match result {
+ Some(Ok(c)) => {
+ self.machine_st.unify_fixnum(Fixnum::build_with(c as i64), addr);
+ break;
+ }
+ _ => {
+ self.machine_st.eof_action(
+ self.machine_st.registers[2],
+ stream,
+ atom!("get_code"),
+ 2,
+ )?;
+
+ if EOFAction::Reset != stream.options().eof_action() {
+ break;
+ } else if self.machine_st.fail {
+ break;
+ }
+ }
+ }
+ }
+
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn first_stream(&mut self) {
+ let mut first_stream = None;
+ let mut null_streams = BTreeSet::new();
+
+ for stream in self.indices.streams.iter().cloned() {
+ if !stream.is_null_stream() {
+ first_stream = Some(stream);
+ break;
+ } else {
+ null_streams.insert(stream);
+ }
+ }
+
+ self.indices.streams = self.indices.streams.sub(&null_streams);
+
+ if let Some(first_stream) = first_stream {
+ let stream = stream_as_cell!(first_stream);
+
+ let var = self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[1]
+ )).as_var().unwrap();
+
+ self.machine_st.bind(var, stream);
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn next_stream(&mut self) {
+ let prev_stream = cell_as_stream!(self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[1]
+ )));
+
+ let mut next_stream = None;
+ let mut null_streams = BTreeSet::new();
+
+ for stream in self.indices
+ .streams
+ .range(prev_stream..)
+ .skip(1)
+ .cloned()
+ {
+ if !stream.is_null_stream() {
+ next_stream = Some(stream);
+ break;
+ } else {
+ null_streams.insert(stream);
+ }
+ }
+
+ self.indices.streams = self.indices.streams.sub(&null_streams);
+
+ if let Some(next_stream) = next_stream {
+ let var = self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[2]
+ )).as_var().unwrap();
+
+ let next_stream = stream_as_cell!(next_stream);
+ self.machine_st.bind(var, next_stream);
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn flush_output(&mut self) -> CallResult {
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("flush_output"),
+ 1,
+ )?;
+
+ if !stream.is_output_stream() {
+ let stub = functor_stub(atom!("flush_output"), 1);
+ let addr = stream_as_cell!(stream);
+
+ let err = self.machine_st.permission_error(
+ Permission::OutputStream,
+ atom!("stream"),
+ addr,
+ );
+
+ return Err(self.machine_st.error_form(err, stub));
+ }
+
+ stream.flush().unwrap();
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn get_single_char(&mut self) -> CallResult {
+ let ctrl_c = KeyEvent {
+ code: KeyCode::Char('c'),
+ modifiers: KeyModifiers::CONTROL,
+ };
+
+ let key = get_key();
+
+ if key == ctrl_c {
+ let stub = functor_stub(atom!("get_single_char"), 1);
+ let err = self.machine_st.interrupt_error();
+ let err = self.machine_st.error_form(err, stub);
+
+ return Err(err);
+ }
+
+ let c = match key.code {
+ KeyCode::Enter => '\n',
+ KeyCode::Tab => '\t',
+ KeyCode::Char(c) => c,
+ _ => unreachable!(),
+ };
+
+ self.machine_st.unify_char(
+ c,
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])),
+ );
+
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn head_is_dynamic(&mut self) {
+ let module_name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[1])
+ ));
+
+ let (name, arity) = read_heap_cell!(
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
+ (HeapCellValueTag::Str, s) => {
+ cell_as_atom_cell!(self.machine_st.heap[s]).get_name_and_arity()
+ }
+ (HeapCellValueTag::Atom, (name, _arity)) => {
+ (name, 0)
+ }
+ _ => {
+ unreachable!()
+ }
+ );
+
+ self.machine_st.fail = !self.indices.is_dynamic_predicate(module_name, (name, arity));
+ }
+
+ #[inline(always)]
+ pub(crate) fn close(&mut self) -> CallResult {
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("close"),
+ 2,
+ )?;
+
+ if !stream.is_input_stream() {
+ stream.flush().unwrap(); // 8.11.6.1b)
+ }
- let n = self.machine_st.store(self.machine_st.deref(n));
+ self.indices.streams.remove(&stream);
- let string = match Number::try_from(n) {
- Ok(Number::Float(OrderedFloat(n))) => {
- format!("{0:<20?}", n)
- }
- Ok(Number::Fixnum(n)) => n.get_num().to_string(),
- Ok(Number::Integer(n)) => n.to_string(),
- Ok(Number::Rational(r)) => {
- // n has already been confirmed as an integer, and
- // internally, Rational is assumed reduced, so its denominator
- // must be 1.
- r.numer().to_string()
- }
- _ => {
- unreachable!()
- }
- };
+ if stream == self.user_input {
+ self.user_input = self.indices
+ .stream_aliases
+ .get(&atom!("user_input"))
+ .cloned()
+ .unwrap();
- let chars_atom = self.machine_st.atom_tbl.build_with(&string.trim());
- self.machine_st.unify_complete_string(chars_atom, self.machine_st.store(self.machine_st.deref(chs)));
- }
- &SystemClauseType::NumberToCodes => {
- let n = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let chs = self.machine_st.registers[2];
+ self.indices.streams.insert(self.user_input);
+ } else if stream == self.user_output {
+ self.user_output = self.indices
+ .stream_aliases
+ .get(&atom!("user_output"))
+ .cloned()
+ .unwrap();
- let string = match Number::try_from(n) {
- Ok(Number::Float(OrderedFloat(n))) => {
- format!("{0:<20?}", n)
- }
- Ok(Number::Fixnum(n)) => n.get_num().to_string(),
- Ok(Number::Integer(n)) => n.to_string(),
- Ok(Number::Rational(r)) => {
- // n has already been confirmed as an integer, and
- // internally, Rational is assumed reduced, so its
- // denominator must be 1.
- r.numer().to_string()
- }
- _ => {
- unreachable!()
- }
- };
+ self.indices.streams.insert(self.user_output);
+ }
- let codes = string.trim().chars().map(|c| {
- fixnum_as_cell!(Fixnum::build_with(c as i64))
- });
+ if !stream.is_stdin() && !stream.is_stdout() && !stream.is_stderr() {
+ let close_result = stream.close();
- let h = iter_to_heap_list(&mut self.machine_st.heap, codes);
- unify!(self.machine_st, heap_loc_as_cell!(h), chs);
+ if let Some(alias) = stream.options().get_alias() {
+ self.indices.stream_aliases.remove(&alias);
}
- &SystemClauseType::CodesToNumber => {
- let stub_gen = || functor_stub(atom!("number_codes"), 2);
- match self.machine_st.try_from_list(self.machine_st.registers[1], stub_gen) {
- Err(e) => {
- return Err(e);
- }
- Ok(addrs) => {
- let string = self.machine_st.codes_to_string(addrs.into_iter(), stub_gen)?;
- self.machine_st.parse_number_from_string(string, &self.indices, stub_gen)?;
- }
- }
- }
- &SystemClauseType::LiftedHeapLength => {
- let a1 = self.machine_st.registers[1];
- let lh_len = Fixnum::build_with(self.machine_st.lifted_heap.len() as i64);
+ if let Err(_) = close_result {
+ let stub = functor_stub(atom!("close"), 1);
+ let addr = stream_as_cell!(stream);
+ let err = self.machine_st.existence_error(ExistenceError::Stream(addr));
- self.machine_st.unify_fixnum(lh_len, a1);
+ return Err(self.machine_st.error_form(err, stub));
}
- &SystemClauseType::CharCode => {
- let stub_gen = || functor_stub(atom!("char_code"), 2);
- let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ }
- let c = read_heap_cell!(a1,
- (HeapCellValueTag::Atom, (name, _arity)) => {
- name.as_char().unwrap()
- }
- (HeapCellValueTag::Char, c) => {
- c
- }
- _ => {
- let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
-
- match Number::try_from(a2) {
- Ok(Number::Integer(n)) => {
- let c = match n.to_u32().and_then(std::char::from_u32) {
- Some(c) => c,
- _ => {
- let err = self.machine_st.representation_error(RepFlag::CharacterCode);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- };
+ Ok(())
+ }
- self.machine_st.unify_char(c, a2);
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- Ok(Number::Fixnum(n)) => {
- match u32::try_from(n.get_num()) {
- Ok(n) => {
- if let Some(c) = std::char::from_u32(n) {
- self.machine_st.unify_char(c, a1);
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- }
- _ => {}
- }
+ #[inline(always)]
+ pub(crate) fn copy_to_lifted_heap(&mut self) {
+ let lh_offset = cell_as_fixnum!(
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
+ ).get_num() as usize;
- let err = self.machine_st.representation_error(RepFlag::CharacterCode);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
- }
- );
+ let copy_target = self.machine_st.registers[2];
- self.machine_st.unify_fixnum(
- Fixnum::build_with(c as i64),
- self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
- );
- }
- &SystemClauseType::CharType => {
- let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ let old_threshold = self.machine_st.copy_findall_solution(lh_offset, copy_target);
+ let new_threshold = self.machine_st.lifted_heap.len() - lh_offset;
+
+ self.machine_st.lifted_heap[old_threshold] = heap_loc_as_cell!(new_threshold);
+
+ for addr in self.machine_st.lifted_heap[old_threshold + 1 ..].iter_mut() {
+ *addr -= self.machine_st.heap.len() + lh_offset;
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn delete_attribute(&mut self) {
+ let ls0 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+
+ if let HeapCellValueTag::Lis = ls0.get_tag() {
+ let l1 = ls0.get_value();
+ let ls1 = self.machine_st.store(self.machine_st.deref(heap_loc_as_cell!(l1 + 1)));
+
+ if let HeapCellValueTag::Lis = ls1.get_tag() {
+ let l2 = ls1.get_value();
+
+ let old_addr = self.machine_st.heap[l1+1];
+ let tail = self.machine_st.store(self.machine_st.deref(heap_loc_as_cell!(l2 + 1)));
+
+ let tail = if tail.is_var() {
+ heap_loc_as_cell!(l1 + 1)
+ } else {
+ tail
+ };
- let c = read_heap_cell!(a1,
- (HeapCellValueTag::Char, c) => {
- c
+ let trail_ref = read_heap_cell!(old_addr,
+ (HeapCellValueTag::Var, h) => {
+ TrailRef::AttrVarHeapLink(h)
}
- (HeapCellValueTag::Atom, (name, _arity)) => {
- name.as_char().unwrap()
+ (HeapCellValueTag::Lis, l) => {
+ TrailRef::AttrVarListLink(l1 + 1, l)
}
_ => {
unreachable!()
}
);
- let chars = cell_as_atom!(a2);
- self.machine_st.fail = true; // This predicate fails by default.
-
- macro_rules! macro_check {
- ($id:ident, $name:expr) => {
- if $id!(c) && chars == $name {
- self.machine_st.fail = false;
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- };
- }
+ self.machine_st.heap[l1 + 1] = tail;
+ self.machine_st.trail(trail_ref);
+ }
+ }
+ }
- macro_rules! method_check {
- ($id:ident, $name:expr) => {
- if c.$id() && chars == $name {
- self.machine_st.fail = false;
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- };
- }
+ #[inline(always)]
+ pub(crate) fn delete_head_attribute(&mut self) {
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- macro_check!(alpha_char, atom!("alpha"));
- method_check!(is_alphabetic, atom!("alphabetic"));
- method_check!(is_alphanumeric, atom!("alphanumeric"));
- macro_check!(alpha_numeric_char, atom!("alnum"));
- method_check!(is_ascii, atom!("ascii"));
- method_check!(is_ascii_punctuation, atom!("ascii_ponctuaction"));
- method_check!(is_ascii_graphic, atom!("ascii_graphic"));
- // macro_check!(backslash_char, atom!("backslash"));
- // macro_check!(back_quote_char, atom!("back_quote"));
- macro_check!(binary_digit_char, atom!("binary_digit"));
- // macro_check!(capital_letter_char, atom!("upper"));
- // macro_check!(comment_1_char, "comment_1");
- // macro_check!(comment_2_char, "comment_2");
- method_check!(is_control, atom!("control"));
- // macro_check!(cut_char, atom!("cut"));
- macro_check!(decimal_digit_char, atom!("decimal_digit"));
- // macro_check!(decimal_point_char, atom!("decimal_point"));
- // macro_check!(double_quote_char, atom!("double_quote"));
- macro_check!(exponent_char, atom!("exponent"));
- macro_check!(graphic_char, atom!("graphic"));
- macro_check!(graphic_token_char, atom!("graphic_token"));
- macro_check!(hexadecimal_digit_char, atom!("hexadecimal_digit"));
- macro_check!(layout_char, atom!("layout"));
- method_check!(is_lowercase, atom!("lower"));
- macro_check!(meta_char, atom!("meta"));
- // macro_check!(new_line_char, atom!("new_line"));
- method_check!(is_numeric, atom!("numeric"));
- macro_check!(octal_digit_char, atom!("octal_digit"));
- macro_check!(octet_char, atom!("octet"));
- macro_check!(prolog_char, atom!("prolog"));
- // macro_check!(semicolon_char, atom!("semicolon"));
- macro_check!(sign_char, atom!("sign"));
- // macro_check!(single_quote_char, atom!("single_quote"));
- // macro_check!(small_letter_char, atom!("lower"));
- macro_check!(solo_char, atom!("solo"));
- // macro_check!(space_char, atom!("space"));
- macro_check!(symbolic_hexadecimal_char, atom!("symbolic_hexadecimal"));
- macro_check!(symbolic_control_char, atom!("symbolic_control"));
- method_check!(is_uppercase, atom!("upper"));
- // macro_check!(variable_indicator_char, atom!("variable_indicator"));
- method_check!(is_whitespace, atom!("whitespace"));
- }
- &SystemClauseType::CheckCutPoint => {
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let old_b = cell_as_fixnum!(addr).get_num() as usize;
-
- let prev_b = self.machine_st.stack.index_or_frame(self.machine_st.b).prelude.b;
- let prev_b = self.machine_st.stack.index_or_frame(prev_b).prelude.b;
-
- if prev_b > old_b {
- self.machine_st.fail = true;
- }
- }
- &SystemClauseType::CopyTermWithoutAttrVars => {
- self.machine_st.copy_term(AttrVarPolicy::StripAttributes);
- }
- &SystemClauseType::FetchGlobalVar => {
- let key = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])));
- let addr = self.machine_st.registers[2];
+ debug_assert_eq!(addr.get_tag(), HeapCellValueTag::AttrVar);
- match self.indices.global_variables.get_mut(&key) {
- Some((ref ball, ref mut loc)) => match loc {
- Some(value_loc) => {
- unify_fn!(self.machine_st, addr, *value_loc);
- }
- None if !ball.stub.is_empty() => {
- let h = self.machine_st.heap.len();
- let stub = ball.copy_and_align(h);
+ let h = addr.get_value();
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.heap[h + 1]));
- self.machine_st.heap.extend(stub.into_iter());
+ debug_assert_eq!(addr.get_tag(), HeapCellValueTag::Lis);
- unify_fn!(self.machine_st, addr, heap_loc_as_cell!(h));
+ let l = addr.get_value();
+ let tail = self.machine_st.store(self.machine_st.deref(heap_loc_as_cell!(l + 1)));
- if !self.machine_st.fail {
- *loc = Some(heap_loc_as_cell!(h));
- self.machine_st.trail(TrailRef::BlackboardEntry(key));
- }
- }
- _ => self.machine_st.fail = true,
- },
- None => self.machine_st.fail = true,
- };
- }
- &SystemClauseType::PutCode => {
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("put_code"),
- 2,
- )?;
+ let tail = if tail.is_var() {
+ self.machine_st.heap[h] = heap_loc_as_cell!(h);
+ self.machine_st.trail(TrailRef::Ref(Ref::attr_var(h)));
- self.machine_st.check_stream_properties(
- stream,
- StreamType::Text,
- None,
- atom!("put_code"),
- 2,
- )?;
+ heap_loc_as_cell!(h + 1)
+ } else {
+ tail
+ };
- let stub_gen = || functor_stub(atom!("put_code"), 2);
+ self.machine_st.heap[h + 1] = tail;
+ self.machine_st.trail(TrailRef::AttrVarListLink(h + 1, l));
+ }
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ #[inline(always)]
+ pub(crate) fn dynamic_module_resolution(
+ &mut self,
+ narity: usize,
+ ) -> Result<(Atom, PredicateKey), MachineStub> {
+ let module_name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[1 + narity]
+ )));
+
+ let addr = self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[2 + narity]
+ ));
+
+ read_heap_cell!(addr,
+ (HeapCellValueTag::Str, a) => {
+ let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[a])
+ .get_name_and_arity();
- if addr.is_var() {
- let err = self.machine_st.instantiation_error();
- return Err(self.machine_st.error_form(err, stub_gen()));
- } else {
- match Number::try_from(addr) {
- Ok(Number::Integer(n)) => {
- if let Some(c) = n.to_u32().and_then(|c| char::try_from(c).ok()) {
- write!(&mut stream, "{}", c).unwrap();
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- }
- Ok(Number::Fixnum(n)) => {
- let n = n.get_num();
- if let Some(c) = u32::try_from(n).ok().and_then(|c| char::from_u32(c)) {
- write!(&mut stream, "{}", c).unwrap();
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- }
- _ => {
- let err = self.machine_st.type_error(ValidType::Integer, addr);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
+ for i in (arity + 1..arity + narity + 1).rev() {
+ self.machine_st.registers[i] = self.machine_st.registers[i - arity];
+ }
- let err = self.machine_st.representation_error(RepFlag::CharacterCode);
- return Err(self.machine_st.error_form(err, stub_gen()));
+ for i in 1..arity + 1 {
+ self.machine_st.registers[i] = self.machine_st.heap[a + i];
}
- }
- &SystemClauseType::PutChar => {
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("put_char"),
- 2,
- )?;
- self.machine_st.check_stream_properties(
- stream,
- StreamType::Text,
- None,
- atom!("put_char"),
- 2,
- )?;
+ Ok((module_name, (name, arity + narity)))
+ }
+ (HeapCellValueTag::Atom, (name, _arity)) => {
+ Ok((module_name, (name, narity)))
+ }
+ (HeapCellValueTag::Char, c) => {
+ let key = (self.machine_st.atom_tbl.build_with(&c.to_string()), narity);
+ Ok((module_name, key))
+ }
+ _ => {
+ let stub = functor_stub(atom!("(:)"), 2);
+ let err = self.machine_st.type_error(ValidType::Callable, addr);
- let stub_gen = || functor_stub(atom!("put_char"), 2);
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ Err(self.machine_st.error_form(err, stub))
+ }
+ )
+ }
- if addr.is_var() {
- let err = self.machine_st.instantiation_error();
- return Err(self.machine_st.error_form(err, stub_gen()));
- } else {
- read_heap_cell!(addr,
- (HeapCellValueTag::Atom, (name, _arity)) => {
- let c = name.as_char().unwrap();
- write!(&mut stream, "{}", c).unwrap();
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- (HeapCellValueTag::Char, c) => {
- write!(&mut stream, "{}", c).unwrap();
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- _ => {
- }
- );
+ #[inline(always)]
+ pub(crate) fn enqueue_attributed_var(&mut self) {
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let err = self.machine_st.type_error(ValidType::Character, addr);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
+ read_heap_cell!(addr,
+ (HeapCellValueTag::AttrVar, h) => {
+ self.machine_st.attr_var_init.attr_var_queue.push(h);
+ }
+ _ => {
}
- &SystemClauseType::PutChars => {
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("$put_chars"),
- 2,
- )?;
+ );
+ }
- let mut bytes = Vec::new();
- let stub_gen = || functor_stub(atom!("$put_chars"), 2);
+ #[inline(always)]
+ pub(crate) fn get_next_db_ref(&mut self) {
+ let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- if let Some(string) = self.machine_st.value_to_str_like(self.machine_st.registers[2]) {
- if stream.options().stream_type() == StreamType::Binary {
- for c in string.as_str().chars() {
- if c as u32 > 255 {
- let err = self.machine_st.type_error(ValidType::Byte, char_as_cell!(c));
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
+ if let Some(name_var) = a1.as_var() {
+ let mut iter = self.indices.code_dir.iter();
- bytes.push(c as u8);
- }
- } else {
- bytes = string.as_str().bytes().collect();
- }
+ while let Some(((name, arity), _)) = iter.next() {
+ let arity_var = self.machine_st.deref(self.machine_st.registers[2])
+ .as_var().unwrap();
- match stream.write_all(&bytes) {
- Ok(_) => {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- _ => {
- let addr = stream_as_cell!(stream);
- let err = self.machine_st.existence_error(ExistenceError::Stream(addr));
+ self.machine_st.bind(name_var, atom_as_cell!(name));
+ self.machine_st.bind(arity_var, fixnum_as_cell!(Fixnum::build_with(*arity as i64)));
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
- } else {
+ return;
+ }
+
+ self.machine_st.fail = true;
+ } else if a1.get_tag() == HeapCellValueTag::Atom {
+ let name = cell_as_atom!(a1);
+ let arity = cell_as_fixnum!(self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[2])
+ )).get_num() as usize;
+
+ match self.machine_st.get_next_db_ref(&self.indices, &DBRef::NamedPred(name, arity)) {
+ Some(DBRef::NamedPred(name, arity)) => {
+ let atom_var = self.machine_st.deref(self.machine_st.registers[3])
+ .as_var().unwrap();
+
+ let arity_var = self.machine_st.deref(self.machine_st.registers[4])
+ .as_var().unwrap();
+
+ self.machine_st.bind(atom_var, atom_as_cell!(name));
+ self.machine_st.bind(arity_var, fixnum_as_cell!(Fixnum::build_with(arity as i64)));
+ }
+ Some(DBRef::Op(..)) | None => {
self.machine_st.fail = true;
}
}
- &SystemClauseType::PutByte => {
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("put_byte"),
- 2,
- )?;
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
- self.machine_st.check_stream_properties(
- stream,
- StreamType::Binary,
- None,
- atom!("put_byte"),
- 2,
- )?;
+ #[inline(always)]
+ pub(crate) fn get_next_op_db_ref(&mut self) {
+ let prec = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+
+ if let Some(prec_var) = prec.as_var() {
+ let spec = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ let op = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3]));
+ let orig_op = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[7]));
+
+ let spec_num = if spec.get_tag() == HeapCellValueTag::Atom {
+ (match cell_as_atom!(spec) {
+ atom!("xfx") => XFX,
+ atom!("xfy") => XFY,
+ atom!("yfx") => YFX,
+ atom!("fx") => FX,
+ atom!("fy") => FY,
+ atom!("xf") => XF,
+ _ => unreachable!(),
+ }) as u8
+ } else {
+ 0
+ };
- let stub_gen = || functor_stub(atom!("put_byte"), 2);
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ let unossified_op_dir = if !orig_op.is_var() {
+ let orig_op = cell_as_atom!(orig_op);
- if addr.is_var() {
- let err = self.machine_st.instantiation_error();
- return Err(self.machine_st.error_form(err, stub_gen()));
- } else {
- match Number::try_from(addr) {
- Ok(Number::Integer(n)) => {
- if let Some(nb) = n.to_u8() {
- match stream.write(&mut [nb]) {
- Ok(1) => {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- _ => {
- let err = self.machine_st.existence_error(
- ExistenceError::Stream(stream_as_cell!(stream))
- );
+ let op_descs = [
+ self.indices.op_dir.get_key_value(&(orig_op, Fixity::In)),
+ self.indices.op_dir.get_key_value(&(orig_op, Fixity::Pre)),
+ self.indices.op_dir.get_key_value(&(orig_op, Fixity::Post)),
+ ];
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
- }
- }
- Ok(Number::Fixnum(n)) => {
- if let Ok(nb) = u8::try_from(n.get_num()) {
- match stream.write(&mut [nb]) {
- Ok(1) => {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- _ => {
- let err = self.machine_st.existence_error(
- ExistenceError::Stream(stream_as_cell!(stream))
- );
+ let number_of_keys = op_descs[0].is_some() as usize +
+ op_descs[1].is_some() as usize +
+ op_descs[2].is_some() as usize;
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
+ match number_of_keys {
+ 0 => {
+ self.machine_st.fail = true;
+ return;
+ }
+ 1 => {
+ for op_desc in op_descs {
+ if let Some((_, op_desc)) = op_desc {
+ let (op_prec, op_spec) =
+ (op_desc.get_prec(), op_desc.get_spec());
+
+ let op_spec = match op_spec as u32 {
+ XFX => atom!("xfx"),
+ XFY => atom!("xfy"),
+ YFX => atom!("yfx"),
+ FX => atom!("fx"),
+ FY => atom!("fy"),
+ XF => atom!("xf"),
+ YF => atom!("yf"),
+ _ => unreachable!(),
+ };
+
+ let op_prec = Fixnum::build_with(op_prec as i64);
+
+ self.machine_st.unify_fixnum(op_prec, prec);
+ self.machine_st.unify_atom(op_spec, spec);
}
}
- _ => {
- }
- }
- }
- let err = self.machine_st.type_error(ValidType::Byte, self.machine_st.registers[2]);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- &SystemClauseType::GetByte => {
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("get_byte"),
- 2,
- )?;
-
- self.machine_st.check_stream_properties(
- stream,
- StreamType::Binary,
- Some(self.machine_st.registers[2]),
- atom!("get_byte"),
- 2,
- )?;
-
- if stream.past_end_of_stream() {
- self.machine_st.eof_action(self.machine_st.registers[2], stream, atom!("get_byte"), 2)?;
-
- if EOFAction::Reset != stream.options().eof_action() {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- } else if self.machine_st.fail {
- return Ok(());
+ return;
}
- }
-
- let stub_gen = || functor_stub(atom!("get_byte"), 2);
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ _ => {
+ let mut unossified_op_dir = OssifiedOpDir::new();
- let addr = if addr.is_var() {
- addr
- } else {
- match Number::try_from(addr) {
- Ok(Number::Integer(n)) => {
- if let Some(nb) = n.to_u8() {
- fixnum_as_cell!(Fixnum::build_with(nb as i64))
- } else {
- let err = self.machine_st.type_error(ValidType::InByte, addr);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
- Ok(Number::Fixnum(n)) => {
- if let Ok(nb) = u8::try_from(n.get_num()) {
- fixnum_as_cell!(Fixnum::build_with(nb as i64))
- } else {
- let err = self.machine_st.type_error(ValidType::InByte, addr);
- return Err(self.machine_st.error_form(err, stub_gen()));
+ for op_desc in op_descs {
+ if let Some((key, op_desc)) = op_desc {
+ let (prec, spec) = (op_desc.get_prec(), op_desc.get_spec());
+ unossified_op_dir.insert(*key, (prec as usize, spec as Specifier));
}
}
- _ => {
- let err = self.machine_st.type_error(ValidType::InByte, addr);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
+
+ unossified_op_dir
}
- };
+ }
+ } else {
+ let mut unossified_op_dir = OssifiedOpDir::new();
- loop {
- let mut b = [0u8; 1];
+ unossified_op_dir.extend(self.indices.op_dir.iter().filter_map(
+ |(key, op_desc)| {
+ let (other_prec, other_spec) = (op_desc.get_prec(), op_desc.get_spec());
+ let name = key.0;
- match stream.read(&mut b) {
- Ok(1) => {
- self.machine_st.unify_fixnum(Fixnum::build_with(b[0] as i64), addr);
- break;
- }
- _ => {
- stream.set_past_end_of_stream(true);
- self.machine_st.unify_fixnum(Fixnum::build_with(-1), self.machine_st.registers[2]);
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
+ if other_prec == 0 {
+ return None;
}
- }
- }
- }
- &SystemClauseType::GetChar => {
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("get_char"),
- 2,
- )?;
- self.machine_st.check_stream_properties(
- stream,
- StreamType::Text,
- Some(self.machine_st.registers[2]),
- atom!("get_char"),
- 2,
- )?;
+ if (!orig_op.is_var() && atom_as_cell!(name) != orig_op) ||
+ (!spec.is_var() && other_spec != spec_num) {
+ return None;
+ }
- if stream.past_end_of_stream() {
- if EOFAction::Reset != stream.options().eof_action() {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- } else if self.machine_st.fail {
- return Ok(());
+ Some((*key, (other_prec as usize, other_spec as Specifier)))
}
- }
-
- if stream.at_end_of_stream() {
- let end_of_file = atom!("end_of_file");
- stream.set_past_end_of_stream(true);
+ ));
- self.machine_st.unify_atom(end_of_file, self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])));
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
+ unossified_op_dir
+ };
- let stub_gen = || functor_stub(atom!("get_char"), 2);
- let mut iter = self.machine_st.open_parsing_stream(stream, atom!("get_char"), 2)?;
+ let ossified_op_dir = arena_alloc!(unossified_op_dir, &mut self.machine_st.arena);
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ match ossified_op_dir.iter().next() {
+ Some(((op_atom, _), (op_prec, op_spec))) => {
+ let ossified_op_dir_var = self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[4]
+ )).as_var().unwrap();
- let addr = if addr.is_var() {
- addr
- } else {
- read_heap_cell!(addr,
- (HeapCellValueTag::Atom, (atom, _arity)) => {
- char_as_cell!(atom.as_char().unwrap())
- }
- (HeapCellValueTag::Char) => {
- addr
- }
+ let spec_atom = match *op_spec {
+ FX => atom!("fx"),
+ FY => atom!("fy"),
+ XF => atom!("xf"),
+ YF => atom!("yf"),
+ XFX => atom!("xfx"),
+ XFY => atom!("xfy"),
+ YFX => atom!("yfx"),
_ => {
- let err = self.machine_st.type_error(ValidType::InCharacter, addr);
- return Err(self.machine_st.error_form(err, stub_gen()));
+ self.machine_st.fail = true;
+ return;
}
- )
- };
+ };
+
+ let spec_var = spec.as_var().unwrap();
+ let op_var = op.as_var().unwrap();
- loop {
- let result = iter.read_char();
+ self.machine_st.bind(prec_var, fixnum_as_cell!(Fixnum::build_with(*op_prec as i64)));
+ self.machine_st.bind(spec_var, atom_as_cell!(spec_atom));
+ self.machine_st.bind(op_var, atom_as_cell!(op_atom));
+ self.machine_st.bind(ossified_op_dir_var, typed_arena_ptr_as_cell!(ossified_op_dir));
+ }
+ None => {
+ self.machine_st.fail = true;
+ return;
+ }
+ }
+ } else {
+ let spec = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])));
+ let op_atom = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3])));
+ let ossified_op_dir_cell = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[4]));
- match result {
- Some(Ok(c)) => {
- self.machine_st.unify_char(c, addr);
+ if ossified_op_dir_cell.is_var() {
+ self.machine_st.fail = true;
+ return;
+ }
- if self.machine_st.fail {
- return Ok(());
- }
+ let ossified_op_dir = cell_as_ossified_op_dir!(
+ ossified_op_dir_cell
+ );
- break;
- }
+ let fixity = match spec {
+ atom!("xfy") | atom!("yfx") | atom!("xfx") => Fixity::In,
+ atom!("xf") | atom!("yf") => Fixity::Post,
+ atom!("fx") | atom!("fy") => Fixity::Pre,
+ _ => {
+ self.machine_st.fail = true;
+ return;
+ }
+ };
+
+ match self.machine_st.get_next_db_ref(
+ &self.indices,
+ &DBRef::Op(op_atom, fixity, ossified_op_dir),
+ ) {
+ Some(DBRef::Op(op_atom, fixity, ossified_op_dir)) => {
+ let (prec, spec) = ossified_op_dir.get(&(op_atom, fixity)).unwrap();
+
+ let prec_var = self.machine_st.deref(self.machine_st.registers[5])
+ .as_var().unwrap();
+
+ let spec_var = self.machine_st.deref(self.machine_st.registers[6])
+ .as_var().unwrap();
+
+ let op_var = self.machine_st.deref(self.machine_st.registers[7])
+ .as_var().unwrap();
+
+ let spec_atom = match *spec {
+ FX => atom!("fx"),
+ FY => atom!("fy"),
+ XF => atom!("xf"),
+ YF => atom!("yf"),
+ XFX => atom!("xfx"),
+ XFY => atom!("xfy"),
+ YFX => atom!("yfx"),
_ => {
- self.machine_st.eof_action(
- self.machine_st.registers[2],
- stream,
- atom!("get_char"),
- 2,
- )?;
-
- if EOFAction::Reset != stream.options().eof_action() {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- } else if self.machine_st.fail {
- return Ok(());
- }
+ self.machine_st.fail = true;
+ return;
}
- }
+ };
+
+ self.machine_st.bind(prec_var, fixnum_as_cell!(Fixnum::build_with(*prec as i64)));
+ self.machine_st.bind(spec_var, atom_as_cell!(spec_atom));
+ self.machine_st.bind(op_var, atom_as_cell!(op_atom));
+ }
+ Some(DBRef::NamedPred(..)) | None => {
+ self.machine_st.fail = true;
}
}
- &SystemClauseType::GetNChars => {
- let stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("get_n_chars"),
- 3,
- )?;
+ }
+ }
- let num = match Number::try_from(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]))) {
- Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).unwrap(),
- Ok(Number::Integer(n)) => match n.to_usize() {
- Some(u) => u,
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- },
- _ => {
- unreachable!()
- }
- };
+ #[inline(always)]
+ pub(crate) fn maybe(&mut self) {
+ let result = {
+ let mut rand = RANDOM_STATE.borrow_mut();
+ rand.bits(1) == 0
+ };
- let mut string = String::new();
+ self.machine_st.fail = result;
+ }
- if stream.options().stream_type() == StreamType::Binary {
- let mut buf = vec![];
- let mut chunk = stream.take(num as u64);
+ #[inline(always)]
+ pub(crate) fn cpu_now(&mut self) {
+ let secs = ProcessTime::now().as_duration().as_secs_f64();
+ let secs = arena_alloc!(OrderedFloat(secs), &mut self.machine_st.arena);
- chunk.read_to_end(&mut buf).ok();
+ self.machine_st.unify_f64(secs, self.machine_st.registers[1]);
+ }
- for c in buf {
- string.push(c as char);
- }
- } else {
- let mut iter = self.machine_st.open_parsing_stream(stream, atom!("get_n_chars"), 2)?;
+ #[inline(always)]
+ pub(crate) fn current_time(&mut self) {
+ let timestamp = self.systemtime_to_timestamp(SystemTime::now());
+ self.machine_st.unify_atom(timestamp, self.machine_st.registers[1]);
+ }
- for _ in 0..num {
- let result = iter.read_char();
+ #[inline(always)]
+ pub(crate) fn open(&mut self) -> CallResult {
+ let alias = self.machine_st.registers[4];
+ let eof_action = self.machine_st.registers[5];
+ let reposition = self.machine_st.registers[6];
+ let stream_type = self.machine_st.registers[7];
- match result {
- Some(Ok(c)) => {
- string.push(c);
- }
- _ => {
- break;
- }
- }
- }
- };
+ let options = self.machine_st.to_stream_options(alias, eof_action, reposition, stream_type);
+ let src_sink = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let atom = self.machine_st.atom_tbl.build_with(&string);
- self.machine_st.unify_complete_string(atom, self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3])));
- }
- &SystemClauseType::GetCode => {
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("get_code"),
- 2,
- )?;
-
- self.machine_st.check_stream_properties(
- stream,
- StreamType::Text,
- Some(self.machine_st.registers[2]),
- atom!("get_code"),
- 2,
- )?;
-
- if stream.past_end_of_stream() {
- if EOFAction::Reset != stream.options().eof_action() {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- } else if self.machine_st.fail {
- return Ok(());
- }
+ if let Some(str_like) = self.machine_st.value_to_str_like(src_sink) {
+ let file_spec = match str_like {
+ AtomOrString::Atom(atom) => {
+ atom
}
-
- if stream.at_end_of_stream() {
- let end_of_file = atom!("end_of_file");
-
- stream.set_past_end_of_stream(true);
-
- self.machine_st.unify_atom(end_of_file, self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])));
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
+ AtomOrString::String(string) => {
+ self.machine_st.atom_tbl.build_with(&string)
}
+ };
- let stub_gen = || functor_stub(atom!("get_code"), 2);
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ let mut stream = self.machine_st.stream_from_file_spec(
+ file_spec,
+ &mut self.indices,
+ &options,
+ )?;
- let addr = if addr.is_var() {
- addr
- } else {
- match Number::try_from(addr) {
- Ok(Number::Integer(n)) => {
- let n = n
- .to_u32()
- .and_then(|n| std::char::from_u32(n));
-
- if let Some(n) = n {
- fixnum_as_cell!(Fixnum::build_with(n as i64))
- } else {
- let err = self.machine_st.representation_error(RepFlag::InCharacterCode);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
- Ok(Number::Fixnum(n)) => {
- let nf = u32::try_from(n.get_num())
- .ok()
- .and_then(|n| std::char::from_u32(n));
-
- if nf.is_some() {
- fixnum_as_cell!(n)
- } else {
- let err = self.machine_st.representation_error(RepFlag::InCharacterCode);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
- _ => {
- let err = self.machine_st.type_error(ValidType::Integer, self.machine_st.registers[2]);
- return Err(self.machine_st.error_form(err, stub_gen()));
- }
- }
- };
+ *stream.options_mut() = options;
+ self.indices.streams.insert(stream);
- let mut iter = self.machine_st.open_parsing_stream(stream.clone(), atom!("get_code"), 2)?;
+ if let Some(alias) = stream.options().get_alias() {
+ self.indices.stream_aliases.insert(alias, stream);
+ }
- loop {
- let result = iter.read_char();
+ let stream_var = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3]));
+ self.machine_st.bind(stream_var.as_var().unwrap(), stream_as_cell!(stream));
+ } else {
+ let err = self.machine_st.domain_error(DomainErrorType::SourceSink, src_sink);
+ let stub = functor_stub(atom!("open"), 4);
- match result {
- Some(Ok(c)) => {
- self.machine_st.unify_fixnum(Fixnum::build_with(c as i64), addr);
+ return Err(self.machine_st.error_form(err, stub));
+ }
- if self.machine_st.fail {
- return Ok(());
- }
+ Ok(())
+ }
- break;
- }
- _ => {
- self.machine_st.eof_action(
- self.machine_st.registers[2],
- stream,
- atom!("get_code"),
- 2,
- )?;
-
- if EOFAction::Reset != stream.options().eof_action() {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- } else if self.machine_st.fail {
- return Ok(());
- }
- }
- }
- }
- }
- &SystemClauseType::FirstStream => {
- let mut first_stream = None;
- let mut null_streams = BTreeSet::new();
+ #[inline(always)]
+ pub(crate) fn op_declaration(&mut self) -> CallResult {
+ let priority = self.machine_st.registers[1];
+ let specifier = self.machine_st.registers[2];
+ let op = self.machine_st.registers[3];
- for stream in self.indices.streams.iter().cloned() {
- if !stream.is_null_stream() {
- first_stream = Some(stream);
- break;
- } else {
- null_streams.insert(stream);
- }
- }
+ let priority = self.machine_st.store(self.machine_st.deref(priority));
- self.indices.streams = self.indices.streams.sub(&null_streams);
+ let priority = match Number::try_from(priority) {
+ Ok(Number::Integer(n)) => n.to_u16().unwrap(),
+ Ok(Number::Fixnum(n)) => u16::try_from(n.get_num()).unwrap(),
+ _ => {
+ unreachable!();
+ }
+ };
- if let Some(first_stream) = first_stream {
- let stream = stream_as_cell!(first_stream);
+ let specifier = cell_as_atom_cell!(self.machine_st.store(self.machine_st.deref(specifier)))
+ .get_name();
- let var = self.machine_st.store(self.machine_st.deref(
- self.machine_st.registers[1]
- )).as_var().unwrap();
+ let op = read_heap_cell!(self.machine_st.store(self.machine_st.deref(op)),
+ (HeapCellValueTag::Char) => {
+ self.machine_st.atom_tbl.build_with(&op.to_string())
+ }
+ (HeapCellValueTag::Atom, (name, _arity)) => {
+ name
+ }
+ _ => {
+ unreachable!()
+ }
+ );
- self.machine_st.bind(var, stream);
+ let result = to_op_decl(priority, specifier, op)
+ .map_err(SessionError::from)
+ .and_then(|mut op_decl| {
+ if op_decl.op_desc.get_prec() == 0 {
+ Ok(op_decl.remove(&mut self.indices.op_dir))
} else {
- self.machine_st.fail = true;
- return Ok(());
+ let spec = get_op_desc(
+ op_decl.name,
+ &CompositeOpDir::new(&self.indices.op_dir, None),
+ );
+
+ op_decl.submit(spec, &mut self.indices.op_dir)
}
+ });
+
+ match result {
+ Ok(()) => Ok(()),
+ Err(e) => {
+ // 8.14.3.3 l)
+ let err = self.machine_st.session_error(e);
+ let stub = functor_stub(atom!("op"), 3);
+
+ Err(self.machine_st.error_form(err, stub))
}
- &SystemClauseType::NextStream => {
- let prev_stream = cell_as_stream!(self.machine_st.store(self.machine_st.deref(
- self.machine_st.registers[1]
- )));
+ }
+ }
- let mut next_stream = None;
- let mut null_streams = BTreeSet::new();
+ #[inline(always)]
+ pub(crate) fn set_stream_options(&mut self) -> CallResult {
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("open"),
+ 4,
+ )?;
+
+ let alias = self.machine_st.registers[2];
+ let eof_action = self.machine_st.registers[3];
+ let reposition = self.machine_st.registers[4];
+ let stream_type = self.machine_st.registers[5];
+
+ let options = self.machine_st.to_stream_options(alias, eof_action, reposition, stream_type);
+ *stream.options_mut() = options;
- for stream in self.indices
- .streams
- .range(prev_stream..)
- .skip(1)
- .cloned()
- {
- if !stream.is_null_stream() {
- next_stream = Some(stream);
- break;
- } else {
- null_streams.insert(stream);
- }
- }
+ Ok(())
+ }
- self.indices.streams = self.indices.streams.sub(&null_streams);
+ #[inline(always)]
+ pub(crate) fn truncate_if_no_lifted_heap_growth_diff(&mut self) {
+ self.machine_st.truncate_if_no_lifted_heap_diff(|h| heap_loc_as_cell!(h))
+ }
- if let Some(next_stream) = next_stream {
- let var = self.machine_st.store(self.machine_st.deref(
- self.machine_st.registers[2]
- )).as_var().unwrap();
+ #[inline(always)]
+ pub(crate) fn truncate_if_no_lifted_heap_growth(&mut self) {
+ self.machine_st.truncate_if_no_lifted_heap_diff(|_| empty_list_as_cell!())
+ }
+
+ #[inline(always)]
+ pub(crate) fn get_attributed_variable_list(&mut self) {
+ let attr_var = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let attr_var_list = read_heap_cell!(attr_var,
+ (HeapCellValueTag::AttrVar, h) => {
+ h + 1
+ }
+ (HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
+ // create an AttrVar in the heap.
+ let h = self.machine_st.heap.len();
- let next_stream = stream_as_cell!(next_stream);
+ self.machine_st.heap.push(attr_var_as_cell!(h));
+ self.machine_st.heap.push(heap_loc_as_cell!(h+1));
- self.machine_st.bind(var, next_stream);
- } else {
- self.machine_st.fail = true;
- return Ok(());
- }
+ self.machine_st.bind(Ref::attr_var(h), attr_var);
+ h + 1
+ }
+ _ => {
+ self.machine_st.fail = true;
+ return;
}
- &SystemClauseType::FlushOutput => {
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("flush_output"),
- 1,
- )?;
+ );
- if !stream.is_output_stream() {
- let stub = functor_stub(atom!("flush_output"), 1);
- let addr = stream_as_cell!(stream); // vec![HeapCellValue::Stream(stream)];
+ let list_addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ self.machine_st.bind(Ref::heap_cell(attr_var_list), list_addr);
+ }
- let err = self.machine_st.permission_error(
- Permission::OutputStream,
- atom!("stream"),
- addr,
- );
+ #[inline(always)]
+ pub(crate) fn get_attr_var_queue_delimiter(&mut self) {
+ let addr = self.machine_st.registers[1];
+ let value = Fixnum::build_with(self.machine_st.attr_var_init.attr_var_queue.len() as i64);
- return Err(self.machine_st.error_form(err, stub));
- }
+ self.machine_st.unify_fixnum(value, self.machine_st.store(self.machine_st.deref(addr)));
+ }
- stream.flush().unwrap();
+ #[inline(always)]
+ pub(crate) fn get_attr_var_queue_beyond(&mut self) {
+ let addr = self.machine_st.registers[1];
+ let addr = self.machine_st.store(self.machine_st.deref(addr));
+
+ let b = match Number::try_from(addr) {
+ Ok(Number::Integer(n)) => n.to_usize(),
+ Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
+ _ => {
+ self.machine_st.fail = true;
+ return;
}
- &SystemClauseType::GetSingleChar => {
- let ctrl_c = KeyEvent {
- code: KeyCode::Char('c'),
- modifiers: KeyModifiers::CONTROL,
- };
+ };
- let key = get_key();
+ if let Some(b) = b {
+ let iter = self.machine_st.gather_attr_vars_created_since(b);
- if key == ctrl_c {
- let stub = functor_stub(atom!("get_single_char"), 1);
- let err = self.machine_st.interrupt_error();
- let err = self.machine_st.error_form(err, stub);
+ let var_list_addr = heap_loc_as_cell!(
+ iter_to_heap_list(&mut self.machine_st.heap, iter)
+ );
- return Err(err);
- }
+ let list_addr = self.machine_st.registers[2];
+ unify!(self.machine_st, var_list_addr, list_addr);
+ }
+ }
- let c = match key.code {
- KeyCode::Enter => '\n',
- KeyCode::Tab => '\t',
- KeyCode::Char(c) => c,
- _ => unreachable!(),
- };
+ #[inline(always)]
+ pub(crate) fn get_continuation_chunk(&mut self) {
+ let e = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let e = cell_as_fixnum!(e).get_num() as usize;
- self.machine_st.unify_char(c, self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])));
- }
- &SystemClauseType::HeadIsDynamic => {
- let module_name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])));
+ let p_functor = self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[2]
+ ));
- let (name, arity) = read_heap_cell!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
- (HeapCellValueTag::Str, s) => {
- cell_as_atom_cell!(self.machine_st.heap[s]).get_name_and_arity()
- }
- (HeapCellValueTag::Atom, (name, _arity)) => {
- (name, 0)
- }
- _ => {
- unreachable!()
- }
- );
+ let p = to_local_code_ptr(&self.machine_st.heap, p_functor).unwrap();
- self.machine_st.fail = !self.indices.is_dynamic_predicate(module_name, (name, arity));
- }
- &SystemClauseType::Close => {
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("close"),
- 2,
- )?;
+ let num_cells = *self.code[p].perm_vars_mut().unwrap();
+ let mut addrs = vec![];
- if !stream.is_input_stream() {
- stream.flush().unwrap(); // 8.11.6.1b)
- }
+ for idx in 1..num_cells + 1 {
+ addrs.push(self.machine_st.stack[stack_loc!(AndFrame, e, idx)]);
+ }
- self.indices.streams.remove(&stream);
+ let chunk = str_loc_as_cell!(self.machine_st.heap.len());
- if stream == self.user_input {
- self.user_input = self.indices
- .stream_aliases
- .get(&atom!("user_input"))
- .cloned()
- .unwrap();
+ self.machine_st.heap.push(atom_as_cell!(atom!("cont_chunk"), 1 + num_cells));
+ self.machine_st.heap.push(p_functor);
+ self.machine_st.heap.extend(addrs);
- self.indices.streams.insert(self.user_input);
- } else if stream == self.user_output {
- self.user_output = self.indices
- .stream_aliases
- .get(&atom!("user_output"))
- .cloned()
- .unwrap();
+ unify!(self.machine_st, self.machine_st.registers[3], chunk);
+ }
- self.indices.streams.insert(self.user_output);
- }
+ #[inline(always)]
+ pub(crate) fn get_lifted_heap_from_offset_diff(&mut self) {
+ let lh_offset = self.machine_st.registers[1];
+ let lh_offset = cell_as_fixnum!(
+ self.machine_st.store(self.machine_st.deref(lh_offset))
+ ).get_num() as usize;
- if !stream.is_stdin() && !stream.is_stdout() && !stream.is_stderr() {
- let close_result = stream.close();
+ if lh_offset >= self.machine_st.lifted_heap.len() {
+ let solutions = self.machine_st.registers[2];
+ let diff = self.machine_st.registers[3];
- if let Some(alias) = stream.options().get_alias() {
- self.indices.stream_aliases.remove(&alias);
- }
- if let Err(_) = close_result {
- let stub = functor_stub(atom!("close"), 1);
- let addr = stream_as_cell!(stream);
- let err = self.machine_st.existence_error(ExistenceError::Stream(addr));
+ unify_fn!(self.machine_st, solutions, diff);
+ } else {
+ let h = self.machine_st.heap.len();
+ let mut last_index = h;
- return Err(self.machine_st.error_form(err, stub));
- }
- }
+ for value in self.machine_st.lifted_heap[lh_offset ..].iter().cloned() {
+ last_index = self.machine_st.heap.len();
+ self.machine_st.heap.push(value + h);
}
- &SystemClauseType::CopyToLiftedHeap => {
- let lh_offset = cell_as_fixnum!(
- self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
- ).get_num() as usize;
- let copy_target = self.machine_st.registers[2];
+ if last_index < self.machine_st.heap.len() {
+ let diff = self.machine_st.registers[3];
+ unify_fn!(self.machine_st, diff, self.machine_st.heap[last_index]);
+ }
- let old_threshold = self.machine_st.copy_findall_solution(lh_offset, copy_target);
- let new_threshold = self.machine_st.lifted_heap.len() - lh_offset;
+ self.machine_st.lifted_heap.truncate(lh_offset);
- self.machine_st.lifted_heap[old_threshold] = heap_loc_as_cell!(new_threshold);
+ let solutions = self.machine_st.registers[2];
+ unify_fn!(self.machine_st, heap_loc_as_cell!(h), solutions);
+ }
+ }
- for addr in self.machine_st.lifted_heap[old_threshold + 1 ..].iter_mut() {
- *addr -= self.machine_st.heap.len() + lh_offset;
- }
- },
- &SystemClauseType::DeleteAttribute => {
- let ls0 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ #[inline(always)]
+ pub(crate) fn get_lifted_heap_from_offset(&mut self) {
+ let lh_offset = self.machine_st.registers[1];
+ let lh_offset = cell_as_fixnum!(self.machine_st.store(self.machine_st.deref(
+ lh_offset
+ ))).get_num() as usize;
+
+ if lh_offset >= self.machine_st.lifted_heap.len() {
+ let solutions = self.machine_st.registers[2];
+ unify_fn!(self.machine_st, solutions, empty_list_as_cell!());
+ } else {
+ let h = self.machine_st.heap.len();
- if let HeapCellValueTag::Lis = ls0.get_tag() {
- let l1 = ls0.get_value();
- let ls1 = self.machine_st.store(self.machine_st.deref(heap_loc_as_cell!(l1 + 1)));
+ for addr in self.machine_st.lifted_heap[lh_offset..].iter().cloned() {
+ self.machine_st.heap.push(addr + h);
+ }
- if let HeapCellValueTag::Lis = ls1.get_tag() {
- let l2 = ls1.get_value();
+ self.machine_st.lifted_heap.truncate(lh_offset);
- let old_addr = self.machine_st.heap[l1+1];
- let tail = self.machine_st.store(self.machine_st.deref(heap_loc_as_cell!(l2 + 1)));
+ let solutions = self.machine_st.registers[2];
+ unify_fn!(self.machine_st, heap_loc_as_cell!(h), solutions);
+ }
+ }
- let tail = if tail.is_var() {
- heap_loc_as_cell!(l1 + 1)
- } else {
- tail
- };
+ #[inline(always)]
+ pub(crate) fn get_double_quotes(&mut self) {
+ let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+
+ self.machine_st.unify_atom(
+ match self.machine_st.flags.double_quotes {
+ DoubleQuotes::Chars => atom!("chars"),
+ DoubleQuotes::Atom => atom!("atom"),
+ DoubleQuotes::Codes => atom!("codes"),
+ },
+ a1,
+ );
+ }
- let trail_ref = read_heap_cell!(old_addr,
- (HeapCellValueTag::Var, h) => {
- TrailRef::AttrVarHeapLink(h)
- }
- (HeapCellValueTag::Lis, l) => {
- TrailRef::AttrVarListLink(l1 + 1, l)
- }
- _ => {
- unreachable!()
- }
- );
+ #[inline(always)]
+ pub(crate) fn get_scc_cleaner(&mut self) {
+ let dest = self.machine_st.registers[1];
- self.machine_st.heap[l1 + 1] = tail;
- self.machine_st.trail(trail_ref);
- }
+ if let Some((addr, b_cutoff, prev_b)) = self.machine_st.cont_pts.pop() {
+ let b = self.machine_st.stack.index_or_frame(self.machine_st.b).prelude.b;
+
+ if b <= b_cutoff {
+ self.machine_st.block = prev_b;
+
+ if let Some(r) = dest.as_var() {
+ self.machine_st.bind(r, addr);
+ return;
}
+ } else {
+ self.machine_st.cont_pts.push((addr, b_cutoff, prev_b));
}
- &SystemClauseType::DeleteHeadAttribute => {
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ }
- debug_assert_eq!(addr.get_tag(), HeapCellValueTag::AttrVar);
+ self.machine_st.fail = true;
+ }
- let h = addr.get_value();
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.heap[h + 1]));
+ #[inline(always)]
+ pub(crate) fn halt(&mut self) {
+ let code = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+
+ let code = match Number::try_from(code) {
+ Ok(Number::Fixnum(n)) => i32::try_from(n.get_num()).unwrap(),
+ Ok(Number::Integer(n)) => n.to_i32().unwrap(),
+ Ok(Number::Rational(r)) => {
+ // n has already been confirmed as an integer, and
+ // internally, Rational is assumed reduced, so its
+ // denominator must be 1.
+ r.numer().to_i32().unwrap()
+ }
+ _ => {
+ unreachable!()
+ }
+ };
- debug_assert_eq!(addr.get_tag(), HeapCellValueTag::Lis);
+ std::process::exit(code);
+ }
- let l = addr.get_value();
- let tail = self.machine_st.store(self.machine_st.deref(heap_loc_as_cell!(l + 1)));
+ #[inline(always)]
+ pub(crate) fn install_scc_cleaner(&mut self) {
+ let addr = self.machine_st.registers[1];
+ let b = self.machine_st.b;
+ let prev_block = self.machine_st.block;
- let tail = if tail.is_var() {
- self.machine_st.heap[h] = heap_loc_as_cell!(h);
- self.machine_st.trail(TrailRef::Ref(Ref::attr_var(h)));
+ self.machine_st.run_cleaners_fn = Machine::run_cleaners;
- heap_loc_as_cell!(h + 1)
- } else {
- tail
- };
+ self.machine_st.install_new_block(self.machine_st.registers[2]);
+ self.machine_st.cont_pts.push((addr, b, prev_block));
+ }
+
+ #[inline(always)]
+ pub(crate) fn install_inference_counter(&mut self) -> CallResult {
+ // A1 = B, A2 = L
+ let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+
+ let n = match Number::try_from(a2) {
+ Ok(Number::Fixnum(bp)) => bp.get_num() as usize,
+ Ok(Number::Integer(n)) => n.to_usize().unwrap(),
+ _ => {
+ let stub = functor_stub(
+ atom!("call_with_inference_limit"),
+ 3,
+ );
- self.machine_st.heap[h + 1] = tail;
- self.machine_st.trail(TrailRef::AttrVarListLink(h + 1, l));
+ let err = self.machine_st.type_error(ValidType::Integer, a2);
+ return Err(self.machine_st.error_form(err, stub));
}
- &SystemClauseType::DynamicModuleResolution(narity) => {
- let module_name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(
- self.machine_st.registers[1 + narity]
- )));
+ };
- let addr = self.machine_st.store(self.machine_st.deref(
- self.machine_st.registers[2 + narity]
- ));
+ let bp = cell_as_fixnum!(a1).get_num() as usize;
+ let count = self.machine_st.cwil.add_limit(n, bp);
+ let count = arena_alloc!(count.clone(), &mut self.machine_st.arena);
- read_heap_cell!(addr,
- (HeapCellValueTag::Str, a) => {
- let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[a])
- .get_name_and_arity();
+ self.machine_st.increment_call_count_fn = MachineState::increment_call_count;
- for i in (arity + 1..arity + narity + 1).rev() {
- self.machine_st.registers[i] = self.machine_st.registers[i - arity];
- }
+ let a3 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3]));
+ self.machine_st.unify_big_int(count, a3);
- for i in 1..arity + 1 {
- self.machine_st.registers[i] = self.machine_st.heap[a + i];
- }
+ Ok(())
+ }
- return self.call_clause_type(module_name, (name, arity + narity));
- }
- (HeapCellValueTag::Atom, (name, _arity)) => {
- return self.call_clause_type(module_name, (name, narity));
- }
- (HeapCellValueTag::Char, c) => {
- let key = (self.machine_st.atom_tbl.build_with(&c.to_string()), narity);
- return self.call_clause_type(module_name, key);
- }
- _ => {
- let stub = functor_stub(atom!("(:)"), 2);
- let err = self.machine_st.type_error(ValidType::Callable, addr);
+ #[inline(always)]
+ pub(crate) fn module_exists(&mut self) {
+ let module = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let module_name = cell_as_atom!(module);
- return Err(self.machine_st.error_form(err, stub));
+ self.machine_st.fail = !self.indices.modules.contains_key(&module_name);
+ }
+
+ #[inline(always)]
+ pub(crate) fn no_such_predicate(&mut self) -> CallResult {
+ let module_name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[1]
+ )));
+
+ let head = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+
+ self.machine_st.fail = read_heap_cell!(head,
+ (HeapCellValueTag::Str, s) => {
+ let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
+ .get_name_and_arity();
+
+ let ct = ClauseType::from(name, arity);
+
+ if ct.is_inlined() || ct.is_builtin() {
+ true
+ } else {
+ let index = self.indices.get_predicate_code_index(
+ name,
+ arity,
+ module_name,
+ )
+ .map(|index| index.get())
+ .unwrap_or(IndexPtr::DynamicUndefined);
+
+ match index {
+ IndexPtr::DynamicUndefined | IndexPtr::Undefined => false,
+ _ => true,
}
- );
+ }
}
- &SystemClauseType::EnqueueAttributedVar => {
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ (HeapCellValueTag::Atom, (name, arity)) => {
+ debug_assert_eq!(arity, 0);
- read_heap_cell!(addr,
- (HeapCellValueTag::AttrVar, h) => {
- self.machine_st.attr_var_init.attr_var_queue.push(h);
- }
- _ => {
+ let ct = ClauseType::from(name, 0);
+
+ if ct.is_inlined() || ct.is_builtin() {
+ true
+ } else {
+ let index = self.indices.get_predicate_code_index(
+ name,
+ 0,
+ module_name,
+ )
+ .map(|index| index.get())
+ .unwrap_or(IndexPtr::DynamicUndefined);
+
+ match index {
+ IndexPtr::DynamicUndefined => false,
+ _ => true,
}
- );
+ }
}
- &SystemClauseType::GetNextDBRef => {
- let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ _ => {
+ let err = self.machine_st.type_error(ValidType::Callable, head);
+ let stub = functor_stub(atom!("clause"), 2);
- if let Some(name_var) = a1.as_var() {
- let mut iter = self.indices.code_dir.iter();
+ return Err(self.machine_st.error_form(err, stub));
+ }
+ );
- while let Some(((name, arity), _)) = iter.next() {
- if SystemClauseType::from(*name, *arity).is_some() {
- continue;
- }
+ Ok(())
+ }
+ #[inline(always)]
+ pub(crate) fn redo_attr_var_binding(&mut self) {
+ let var = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let value = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
- let arity_var = self.machine_st.deref(self.machine_st.registers[2])
- .as_var().unwrap();
+ debug_assert_eq!(HeapCellValueTag::AttrVar, var.get_tag());
+ self.machine_st.heap[var.get_value()] = value;
+ }
- self.machine_st.bind(name_var, atom_as_cell!(name));
- self.machine_st.bind(arity_var, fixnum_as_cell!(Fixnum::build_with(*arity as i64)));
+ #[inline(always)]
+ pub(super) fn restore_instr_at_verify_attr_interrupt(&mut self) {
+ match &self.code[VERIFY_ATTR_INTERRUPT_LOC] {
+ &Instruction::VerifyAttrInterrupt => {}
+ _ => {
+ let instr = mem::replace(
+ &mut self.code[VERIFY_ATTR_INTERRUPT_LOC],
+ Instruction::VerifyAttrInterrupt,
+ );
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
+ self.code[self.machine_st.attr_var_init.cp] = instr;
+ }
+ }
+ }
- self.machine_st.fail = true;
- } else if a1.get_tag() == HeapCellValueTag::Atom {
- let name = cell_as_atom!(a1);
- let arity = cell_as_fixnum!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])))
- .get_num() as usize;
+ #[inline(always)]
+ pub(crate) fn reset_attr_var_state(&mut self) { // 1344! That's the value of self.b we need to pop this.
+ self.restore_instr_at_verify_attr_interrupt();
+ self.machine_st.attr_var_init.reset();
+ }
+
+ #[inline(always)]
+ pub(crate) fn remove_call_policy_check(&mut self) {
+ let bp = cell_as_fixnum!(self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[1]
+ ))).get_num() as usize;
+
+ if bp == self.machine_st.b && self.machine_st.cwil.is_empty() {
+ self.machine_st.cwil.reset();
+ self.machine_st.increment_call_count_fn = |_| { Ok(()) };
+ }
+ }
- match self.machine_st.get_next_db_ref(&self.indices, &DBRef::NamedPred(name, arity)) {
- Some(DBRef::NamedPred(name, arity)) => {
- let atom_var = self.machine_st.deref(self.machine_st.registers[3])
- .as_var().unwrap();
+ #[inline(always)]
+ pub(crate) fn remove_inference_counter(&mut self) {
+ let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let bp = cell_as_fixnum!(a1).get_num() as usize;
- let arity_var = self.machine_st.deref(self.machine_st.registers[4])
- .as_var().unwrap();
+ let count = self.machine_st.cwil.remove_limit(bp).clone();
+ let count = arena_alloc!(count.clone(), &mut self.machine_st.arena);
- self.machine_st.bind(atom_var, atom_as_cell!(name));
- self.machine_st.bind(arity_var, fixnum_as_cell!(Fixnum::build_with(arity as i64)));
- }
- Some(DBRef::Op(..)) | None => {
- self.machine_st.fail = true;
- }
- }
- } else {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
- &SystemClauseType::GetNextOpDBRef => {
- let prec = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
-
- if let Some(prec_var) = prec.as_var() {
- let spec = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
- let op = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3]));
- let orig_op = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[7]));
-
- let spec_num = if spec.get_tag() == HeapCellValueTag::Atom {
- (match cell_as_atom!(spec) {
- atom!("xfx") => XFX,
- atom!("xfy") => XFY,
- atom!("yfx") => YFX,
- atom!("fx") => FX,
- atom!("fy") => FY,
- atom!("xf") => XF,
- _ => unreachable!(),
- }) as u8
- } else {
- 0
- };
+ let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+
+ self.machine_st.unify_big_int(count, a2);
+ }
- let unossified_op_dir = if !orig_op.is_var() {
- let orig_op = cell_as_atom!(orig_op);
+ #[inline(always)]
+ pub(crate) fn return_from_verify_attr(&mut self) {
+ let e = self.machine_st.e;
+ let frame_len = self.machine_st.stack.index_and_frame(e).prelude.univ_prelude.num_cells;
- let op_descs = [
- self.indices.op_dir.get_key_value(&(orig_op, Fixity::In)),
- self.indices.op_dir.get_key_value(&(orig_op, Fixity::Pre)),
- self.indices.op_dir.get_key_value(&(orig_op, Fixity::Post)),
- ];
+ for i in 1..frame_len - 2 {
+ self.machine_st.registers[i] = self.machine_st.stack[stack_loc!(AndFrame, e, i)];
+ }
- let number_of_keys = op_descs[0].is_some() as usize +
- op_descs[1].is_some() as usize +
- op_descs[2].is_some() as usize;
+ self.machine_st.b0 = cell_as_fixnum!(self.machine_st.stack[stack_loc!(AndFrame, e, frame_len - 2)])
+ .get_num() as usize;
- match number_of_keys {
- 0 => {
- self.machine_st.fail = true;
- return Ok(());
- }
- 1 => {
- for op_desc in op_descs {
- if let Some((_, op_desc)) = op_desc {
- let (op_prec, op_spec) =
- (op_desc.get_prec(), op_desc.get_spec());
-
- let op_spec = match op_spec as u32 {
- XFX => atom!("xfx"),
- XFY => atom!("xfy"),
- YFX => atom!("yfx"),
- FX => atom!("fx"),
- FY => atom!("fy"),
- XF => atom!("xf"),
- YF => atom!("yf"),
- _ => unreachable!(),
- };
-
- let op_prec = Fixnum::build_with(op_prec as i64);
-
- self.machine_st.unify_fixnum(op_prec, prec);
- self.machine_st.unify_atom(op_spec, spec);
- }
- }
+ self.machine_st.num_of_args = cell_as_fixnum!(self.machine_st.stack[stack_loc!(AndFrame, e, frame_len - 1)])
+ .get_num() as usize;
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- _ => {
- let mut unossified_op_dir = OssifiedOpDir::new();
+ let p = cell_as_fixnum!(self.machine_st.stack[stack_loc!(AndFrame, e, frame_len)]).get_num() as usize;
- for op_desc in op_descs {
- if let Some((key, op_desc)) = op_desc {
- let (prec, spec) = (op_desc.get_prec(), op_desc.get_spec());
- unossified_op_dir.insert(*key, (prec as usize, spec as Specifier));
- }
- }
+ self.machine_st.deallocate();
+ self.machine_st.p = p;
+ }
- unossified_op_dir
- }
- }
- } else {
- let mut unossified_op_dir = OssifiedOpDir::new();
+ #[inline(always)]
+ pub(crate) fn restore_cut_policy(&mut self) {
+ if self.machine_st.cont_pts.is_empty() {
+ self.machine_st.run_cleaners_fn = |_| { false };
+ }
+ }
- unossified_op_dir.extend(self.indices.op_dir.iter().filter_map(
- |(key, op_desc)| {
- let (other_prec, other_spec) = (op_desc.get_prec(), op_desc.get_spec());
- let name = key.0;
+ #[inline(always)]
+ pub(crate) fn set_cut_point(&mut self, r: RegType) -> bool {
+ let cp = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+ self.machine_st.cut_body(cp);
- if other_prec == 0 {
- return None;
- }
+ (self.machine_st.run_cleaners_fn)(self)
+ }
- if (!orig_op.is_var() && atom_as_cell!(name) != orig_op) ||
- (!spec.is_var() && other_spec != spec_num) {
- return None;
- }
+ #[inline(always)]
+ pub(crate) fn set_cut_point_by_default(&mut self, r: RegType) {
+ let cp = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
+ self.machine_st.cut_body(cp);
+ }
- Some((*key, (other_prec as usize, other_spec as Specifier)))
- }
- ));
+ #[inline(always)]
+ pub(crate) fn set_input(&mut self) -> CallResult {
+ let addr = self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[1]
+ ));
+
+ let stream = self.machine_st.get_stream_or_alias(
+ addr,
+ &self.indices.stream_aliases,
+ atom!("set_input"),
+ 1,
+ )?;
+
+ if !stream.is_input_stream() {
+ let stub = functor_stub(atom!("set_input"), 1);
+ let user_alias = atom_as_cell!(atom!("user"));
+
+ let err = self.machine_st.permission_error(
+ Permission::InputStream,
+ atom!("stream"),
+ user_alias,
+ );
- unossified_op_dir
- };
+ return Err(self.machine_st.error_form(err, stub));
+ }
- let ossified_op_dir = arena_alloc!(unossified_op_dir, &mut self.machine_st.arena);
-
- match ossified_op_dir.iter().next() {
- Some(((op_atom, _), (op_prec, op_spec))) => {
- let ossified_op_dir_var = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[4]))
- .as_var().unwrap();
-
- let spec_atom = match *op_spec {
- FX => atom!("fx"),
- FY => atom!("fy"),
- XF => atom!("xf"),
- YF => atom!("yf"),
- XFX => atom!("xfx"),
- XFY => atom!("xfy"),
- YFX => atom!("yfx"),
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- };
+ self.user_input = stream;
+ Ok(())
+ }
- let spec_var = spec.as_var().unwrap();
- let op_var = op.as_var().unwrap();
+ #[inline(always)]
+ pub(crate) fn set_output(&mut self) -> CallResult {
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let stream = self.machine_st.get_stream_or_alias(
+ addr,
+ &self.indices.stream_aliases,
+ atom!("set_output"),
+ 1,
+ )?;
+
+ if !stream.is_output_stream() {
+ let stub = functor_stub(atom!("set_input"), 1);
+
+ let user_alias = atom_as_cell!(atom!("user"));
+ let err = self.machine_st.permission_error(
+ Permission::OutputStream,
+ atom!("stream"),
+ user_alias,
+ );
- self.machine_st.bind(prec_var, fixnum_as_cell!(Fixnum::build_with(*op_prec as i64)));
- self.machine_st.bind(spec_var, atom_as_cell!(spec_atom));
- self.machine_st.bind(op_var, atom_as_cell!(op_atom));
- self.machine_st.bind(ossified_op_dir_var, typed_arena_ptr_as_cell!(ossified_op_dir));
- }
- None => {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
- } else {
- let spec = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])));
- let op_atom = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3])));
- let ossified_op_dir_cell = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[4]));
+ return Err(self.machine_st.error_form(err, stub));
+ }
- if ossified_op_dir_cell.is_var() {
- self.machine_st.fail = true;
- return Ok(());
- }
+ self.user_output = stream;
+ Ok(())
+ }
- let ossified_op_dir = cell_as_ossified_op_dir!(
- ossified_op_dir_cell
- );
+ #[inline(always)]
+ pub(crate) fn set_double_quotes(&mut self) {
+ let atom = cell_as_atom!(self.machine_st.registers[1]);
- let fixity = match spec {
- atom!("xfy") | atom!("yfx") | atom!("xfx") => Fixity::In,
- atom!("xf") | atom!("yf") => Fixity::Post,
- atom!("fx") | atom!("fy") => Fixity::Pre,
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- };
+ self.machine_st.flags.double_quotes = match atom {
+ atom!("atom") => DoubleQuotes::Atom,
+ atom!("chars") => DoubleQuotes::Chars,
+ atom!("codes") => DoubleQuotes::Codes,
+ _ => {
+ self.machine_st.fail = true;
+ return;
+ }
+ };
+ }
- match self.machine_st.get_next_db_ref(
- &self.indices,
- &DBRef::Op(op_atom, fixity, ossified_op_dir),
- ) {
- Some(DBRef::Op(op_atom, fixity, ossified_op_dir)) => {
- let (prec, spec) = ossified_op_dir.get(&(op_atom, fixity)).unwrap();
-
- let prec_var = self.machine_st.deref(self.machine_st.registers[5])
- .as_var().unwrap();
-
- let spec_var = self.machine_st.deref(self.machine_st.registers[6])
- .as_var().unwrap();
-
- let op_var = self.machine_st.deref(self.machine_st.registers[7])
- .as_var().unwrap();
-
- let spec_atom = match *spec {
- FX => atom!("fx"),
- FY => atom!("fy"),
- XF => atom!("xf"),
- YF => atom!("yf"),
- XFX => atom!("xfx"),
- XFY => atom!("xfy"),
- YFX => atom!("yfx"),
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- };
+ #[inline(always)]
+ pub(crate) fn inference_level(&mut self) {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
- self.machine_st.bind(prec_var, fixnum_as_cell!(Fixnum::build_with(*prec as i64)));
- self.machine_st.bind(spec_var, atom_as_cell!(spec_atom));
- self.machine_st.bind(op_var, atom_as_cell!(op_atom));
- }
- Some(DBRef::NamedPred(..)) | None => {
- self.machine_st.fail = true;
- }
- }
- }
- }
- &SystemClauseType::Maybe => {
- let result = {
- let mut rand = RANDOM_STATE.borrow_mut();
- rand.bits(1) == 0
- };
+ let bp = cell_as_fixnum!(a2).get_num() as usize;
+ let prev_b = self.machine_st.stack.index_or_frame(self.machine_st.b).prelude.b;
- self.machine_st.fail = result;
- }
- &SystemClauseType::CpuNow => {
- let secs = ProcessTime::now().as_duration().as_secs_f64();
- let secs = arena_alloc!(OrderedFloat(secs), &mut self.machine_st.arena);
+ if prev_b <= bp {
+ self.machine_st.unify_atom(atom!("!"), a1)
+ } else {
+ self.machine_st.unify_atom(atom!("true"), a1);
+ }
+ }
- self.machine_st.unify_f64(secs, self.machine_st.registers[1]);
- }
- &SystemClauseType::CurrentTime => {
- let timestamp = self.systemtime_to_timestamp(SystemTime::now());
- self.machine_st.unify_atom(timestamp, self.machine_st.registers[1]);
- }
- &SystemClauseType::Open => {
- let alias = self.machine_st.registers[4];
- let eof_action = self.machine_st.registers[5];
- let reposition = self.machine_st.registers[6];
- let stream_type = self.machine_st.registers[7];
+ #[inline(always)]
+ pub(crate) fn clean_up_block(&mut self) {
+ let nb = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let nb = cell_as_fixnum!(nb).get_num() as usize;
- let options = self.machine_st.to_stream_options(alias, eof_action, reposition, stream_type);
- let src_sink = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let b = self.machine_st.b;
- if let Some(str_like) = self.machine_st.value_to_str_like(src_sink) {
- let file_spec = match str_like {
- AtomOrString::Atom(atom) => {
- atom
- }
- AtomOrString::String(string) => {
- self.machine_st.atom_tbl.build_with(&string)
- }
- };
+ if nb > 0 && self.machine_st.stack.index_or_frame(b).prelude.b == nb {
+ self.machine_st.b = self.machine_st.stack.index_or_frame(nb).prelude.b;
+ }
+ }
- let mut stream = self.machine_st.stream_from_file_spec(
- file_spec,
- &mut self.indices,
- &options,
- )?;
+ #[inline(always)]
+ pub(crate) fn erase_ball(&mut self) {
+ self.machine_st.ball.reset();
+ }
- *stream.options_mut() = options;
- self.indices.streams.insert(stream);
+ #[inline(always)]
+ pub(crate) fn get_ball(&mut self) {
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let h = self.machine_st.heap.len();
- if let Some(alias) = stream.options().get_alias() {
- self.indices.stream_aliases.insert(alias, stream);
- }
+ if self.machine_st.ball.stub.len() > 0 {
+ let stub = self.machine_st.ball.copy_and_align(h);
+ self.machine_st.heap.extend(stub.into_iter());
+ } else {
+ self.machine_st.fail = true;
+ return;
+ }
- let stream_var = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3]));
- self.machine_st.bind(stream_var.as_var().unwrap(), stream_as_cell!(stream));
- } else {
- let err = self.machine_st.domain_error(DomainErrorType::SourceSink, src_sink);
- let stub = functor_stub(atom!("open"), 4);
+ match addr.as_var() {
+ Some(r) => self.machine_st.bind(r, self.machine_st.heap[h]),
+ _ => self.machine_st.fail = true,
+ };
+ }
- return Err(self.machine_st.error_form(err, stub));
- }
- }
- &SystemClauseType::OpDeclaration => {
- let priority = self.machine_st.registers[1];
- let specifier = self.machine_st.registers[2];
- let op = self.machine_st.registers[3];
+ #[inline(always)]
+ pub(crate) fn get_current_block(&mut self) {
+ let n = Fixnum::build_with(i64::try_from(self.machine_st.block).unwrap());
+ self.machine_st.unify_fixnum(n, self.machine_st.registers[1]);
+ }
- let priority = self.machine_st.store(self.machine_st.deref(priority));
+ #[inline(always)]
+ pub(crate) fn get_b_value(&mut self) {
+ let n = Fixnum::build_with(i64::try_from(self.machine_st.b).unwrap());
+ self.machine_st.unify_fixnum(n, self.machine_st.registers[1]);
+ }
- let priority = match Number::try_from(priority) {
- Ok(Number::Integer(n)) => n.to_u16().unwrap(),
- Ok(Number::Fixnum(n)) => u16::try_from(n.get_num()).unwrap(),
- _ => {
- unreachable!();
- }
- };
+ #[inline(always)]
+ pub(crate) fn get_cut_point(&mut self) {
+ let n = Fixnum::build_with(i64::try_from(self.machine_st.b0).unwrap());
+ self.machine_st.unify_fixnum(n, self.machine_st.registers[1]);
+ }
- let specifier = cell_as_atom_cell!(self.machine_st.store(self.machine_st.deref(specifier)))
- .get_name();
+ #[inline(always)]
+ pub(crate) fn get_staggered_cut_point(&mut self) {
+ use std::sync::Once;
- let op = read_heap_cell!(self.machine_st.store(self.machine_st.deref(op)),
- (HeapCellValueTag::Char) => {
- self.machine_st.atom_tbl.build_with(&op.to_string())
- }
- (HeapCellValueTag::Atom, (name, _arity)) => {
- name
+ let b = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+
+ static mut SEMICOLON_SECOND_BRANCH_LOC: usize = 0;
+ static LOC_INIT: Once = Once::new();
+
+ let semicolon_second_clause_p = unsafe {
+ LOC_INIT.call_once(|| {
+ match self.indices.code_dir.get(&(atom!(";"), 2)).map(|cell| cell.get()) {
+ Some(IndexPtr::Index(p)) => {
+ match &self.code[p] {
+ &Instruction::TryMeElse(o) => {
+ SEMICOLON_SECOND_BRANCH_LOC = p + o;
+ }
+ _ => {
+ unreachable!();
+ }
+ }
}
_ => {
- unreachable!()
+ unreachable!();
}
- );
+ }
+ });
- let result = to_op_decl(priority, specifier, op)
- .map_err(SessionError::from)
- .and_then(|mut op_decl| {
- if op_decl.op_desc.get_prec() == 0 {
- Ok(op_decl.remove(&mut self.indices.op_dir))
- } else {
- let spec = get_op_desc(
- op_decl.name,
- &CompositeOpDir::new(&self.indices.op_dir, None),
- );
+ SEMICOLON_SECOND_BRANCH_LOC
+ };
- op_decl.submit(spec, &mut self.indices.op_dir)
- }
- });
+ let staggered_b0 = if self.machine_st.b > 0 {
+ let or_frame = self.machine_st.stack.index_or_frame(self.machine_st.b);
- match result {
- Ok(()) => {}
- Err(e) => {
- // 8.14.3.3 l)
- let err = self.machine_st.session_error(e);
- let stub = functor_stub(atom!("op"), 3);
+ if or_frame.prelude.bp == semicolon_second_clause_p {
+ or_frame.prelude.b0
+ } else {
+ self.machine_st.b0
+ }
+ } else {
+ self.machine_st.b0
+ };
- return Err(self.machine_st.error_form(err, stub));
- }
+ let staggered_b0 = integer_as_cell!(
+ Number::arena_from(staggered_b0, &mut self.machine_st.arena)
+ );
+
+ self.machine_st.bind(b.as_var().unwrap(), staggered_b0);
+ }
+
+ #[inline(always)]
+ pub(crate) fn next_ep(&mut self) {
+ let first_arg = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+
+ read_heap_cell!(first_arg,
+ (HeapCellValueTag::Atom, (name, arity)) => {
+ debug_assert_eq!(name, atom!("first"));
+ debug_assert_eq!(arity, 0);
+
+ if self.machine_st.e == 0 {
+ self.machine_st.fail = true;
+ return;
}
- }
- &SystemClauseType::SetStreamOptions => {
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("open"),
- 4,
- )?;
- let alias = self.machine_st.registers[2];
- let eof_action = self.machine_st.registers[3];
- let reposition = self.machine_st.registers[4];
- let stream_type = self.machine_st.registers[5];
+ let and_frame = self.machine_st.stack.index_and_frame(self.machine_st.e);
+ let cp = and_frame.prelude.cp - 1;
- let options = self.machine_st.to_stream_options(alias, eof_action, reposition, stream_type);
- *stream.options_mut() = options;
- }
- &SystemClauseType::TruncateIfNoLiftedHeapGrowthDiff => {
- self.machine_st.truncate_if_no_lifted_heap_diff(|h| heap_loc_as_cell!(h))
- }
- &SystemClauseType::TruncateIfNoLiftedHeapGrowth => {
- self.machine_st.truncate_if_no_lifted_heap_diff(|_| empty_list_as_cell!())
- }
- &SystemClauseType::GetAttributedVariableList => {
- let attr_var = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let attr_var_list = read_heap_cell!(attr_var,
- (HeapCellValueTag::AttrVar, h) => {
- h + 1
- }
- (HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
- // create an AttrVar in the heap.
- let h = self.machine_st.heap.len();
+ let e = and_frame.prelude.e;
+ let e = Fixnum::build_with(i64::try_from(e).unwrap());
- self.machine_st.heap.push(attr_var_as_cell!(h));
- self.machine_st.heap.push(heap_loc_as_cell!(h+1));
+ let p = str_loc_as_cell!(self.machine_st.heap.len());
- self.machine_st.bind(Ref::attr_var(h), attr_var);
- h + 1
- }
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- );
+ self.machine_st.heap.extend(functor!(atom!("dir_entry"), [fixnum(cp)]));
+ self.machine_st.unify_fixnum(e, self.machine_st.registers[2]);
- let list_addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
- self.machine_st.bind(Ref::heap_cell(attr_var_list), list_addr);
+ if !self.machine_st.fail {
+ unify!(self.machine_st, p, self.machine_st.registers[3]);
+ }
}
- &SystemClauseType::GetAttrVarQueueDelimiter => {
- let addr = self.machine_st.registers[1];
- let value = Fixnum::build_with(self.machine_st.attr_var_init.attr_var_queue.len() as i64);
+ (HeapCellValueTag::Fixnum, n) => {
+ let e = n.get_num() as usize;
- self.machine_st.unify_fixnum(value, self.machine_st.store(self.machine_st.deref(addr)));
- }
- &SystemClauseType::GetAttrVarQueueBeyond => {
- let addr = self.machine_st.registers[1];
- let addr = self.machine_st.store(self.machine_st.deref(addr));
+ if e == 0 {
+ self.machine_st.fail = true;
+ return;
+ }
- let b = match Number::try_from(addr) {
- Ok(Number::Integer(n)) => n.to_usize(),
- Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).ok(),
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- };
+ // get the call site so that the number of
+ // active permanent variables can be read from
+ // it later.
+ let and_frame = self.machine_st.stack.index_and_frame(e);
+ let cp = and_frame.prelude.cp - 1;
- if let Some(b) = b {
- let iter = self.machine_st.gather_attr_vars_created_since(b);
+ let p = str_loc_as_cell!(self.machine_st.heap.len());
+ self.machine_st.heap.extend(functor!(atom!("dir_entry"), [fixnum(cp)]));
- let var_list_addr = heap_loc_as_cell!(
- iter_to_heap_list(&mut self.machine_st.heap, iter)
- );
+ let e = Fixnum::build_with(i64::try_from(and_frame.prelude.e).unwrap());
+ self.machine_st.unify_fixnum(e, self.machine_st.registers[2]);
- let list_addr = self.machine_st.registers[2];
- unify!(self.machine_st, var_list_addr, list_addr);
+ if !self.machine_st.fail {
+ unify!(self.machine_st, p, self.machine_st.registers[3]);
}
}
- &SystemClauseType::GetContinuationChunk => {
- let e = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let e = cell_as_fixnum!(e).get_num() as usize;
+ _ => {
+ unreachable!();
+ }
+ );
+ }
- let p_functor = self.machine_st.store(self.machine_st.deref(
- self.machine_st.registers[2]
- ));
- let p = to_local_code_ptr(&self.machine_st.heap, p_functor).unwrap();
+ #[inline(always)]
+ pub(crate) fn points_to_continuation_reset_marker(&mut self) {
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let num_cells = match self.code_repo.lookup_instr(&self.machine_st, &CodePtr::Local(p)) {
- Some(line) => {
- let perm_vars = match line.as_ref(&self.code_repo.code) {
- Line::Control(ref ctrl_instr) => ctrl_instr.perm_vars(),
- _ => None,
- };
+ let p = match to_local_code_ptr(&self.machine_st.heap, addr) {
+ Some(p) => p + 1,
+ None => {
+ self.machine_st.fail = true;
+ return;
+ }
+ };
- perm_vars.unwrap()
- }
- _ => unreachable!(),
- };
+ if !self.is_reset_cont_marker(p) {
+ self.machine_st.fail = true;
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn quoted_token(&mut self) {
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let mut addrs = vec![];
+ read_heap_cell!(addr,
+ (HeapCellValueTag::Fixnum, n) => {
+ let n = u32::try_from(n.get_num()).ok();
+ let n = n.and_then(std::char::from_u32);
- for idx in 1..num_cells + 1 {
- addrs.push(self.machine_st.stack[stack_loc!(AndFrame, e, idx)]);
- }
+ self.machine_st.fail = match n {
+ Some(c) => non_quoted_token(once(c)),
+ None => true,
+ };
+ }
+ (HeapCellValueTag::Char, c) => {
+ self.machine_st.fail = non_quoted_token(once(c));
+ }
+ (HeapCellValueTag::Atom, (name, arity)) => {
+ debug_assert_eq!(arity, 0);
+ self.machine_st.fail = non_quoted_token(name.as_str().chars());
+ }
+ _ => {
+ self.machine_st.fail = true;
+ }
+ );
+ }
- let chunk = str_loc_as_cell!(self.machine_st.heap.len());
+ #[inline(always)]
+ pub(crate) fn read_query_term(&mut self) -> CallResult {
+ self.user_input.reset();
- self.machine_st.heap.push(atom_as_cell!(atom!("cont_chunk"), 1 + num_cells));
- self.machine_st.heap.push(p_functor);
- self.machine_st.heap.extend(addrs);
+ set_prompt(true);
+ let result = self.machine_st.read_term(self.user_input, &mut self.indices);
+ set_prompt(false);
- unify!(self.machine_st, self.machine_st.registers[3], chunk);
+ match result {
+ Ok(()) => Ok(()),
+ Err(e) => {
+ self.user_input = input_stream(&mut self.machine_st.arena);
+ return Err(e);
}
- &SystemClauseType::GetLiftedHeapFromOffsetDiff => {
- let lh_offset = self.machine_st.registers[1];
- let lh_offset = cell_as_fixnum!(self.machine_st.store(self.machine_st.deref(lh_offset))).get_num() as usize;
+ }
+ }
- if lh_offset >= self.machine_st.lifted_heap.len() {
- let solutions = self.machine_st.registers[2];
- let diff = self.machine_st.registers[3];
+ #[inline(always)]
+ pub(crate) fn read_term(&mut self) -> CallResult {
+ set_prompt(false);
- unify_fn!(self.machine_st, solutions, diff);
- } else {
- let h = self.machine_st.heap.len();
- let mut last_index = h;
+ let stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("read_term"),
+ 3,
+ )?;
- for value in self.machine_st.lifted_heap[lh_offset ..].iter().cloned() {
- last_index = self.machine_st.heap.len();
- self.machine_st.heap.push(value + h);
- }
+ self.machine_st.read_term(stream, &mut self.indices)
+ }
- if last_index < self.machine_st.heap.len() {
- let diff = self.machine_st.registers[3];
- unify_fn!(self.machine_st, diff, self.machine_st.heap[last_index]);
- }
+ #[inline(always)]
+ pub(crate) fn read_term_from_chars(&mut self) -> CallResult {
+ if let Some(atom_or_string) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ let chars = atom_or_string.to_string();
+ let stream = Stream::from_owned_string(chars, &mut self.machine_st.arena);
- self.machine_st.lifted_heap.truncate(lh_offset);
+ let term_write_result = match self.machine_st.read(stream, &self.indices.op_dir) {
+ Ok(term_write_result) => term_write_result,
+ Err(e) => {
+ let stub = functor_stub(atom!("read_term_from_chars"), 2);
+ let e = self.machine_st.session_error(SessionError::from(e));
- let solutions = self.machine_st.registers[2];
- unify_fn!(self.machine_st, heap_loc_as_cell!(h), solutions);
+ return Err(self.machine_st.error_form(e, stub));
}
- }
- &SystemClauseType::GetLiftedHeapFromOffset => {
- let lh_offset = self.machine_st.registers[1];
- let lh_offset = cell_as_fixnum!(self.machine_st.store(self.machine_st.deref(lh_offset))).get_num() as usize;
+ };
- if lh_offset >= self.machine_st.lifted_heap.len() {
- let solutions = self.machine_st.registers[2];
- unify_fn!(self.machine_st, solutions, empty_list_as_cell!());
- } else {
- let h = self.machine_st.heap.len();
+ let result = heap_loc_as_cell!(term_write_result.heap_loc);
+ let var = self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[2]
+ )).as_var().unwrap();
- for addr in self.machine_st.lifted_heap[lh_offset..].iter().cloned() {
- self.machine_st.heap.push(addr + h);
- }
+ self.machine_st.bind(var, result);
+ } else {
+ unreachable!()
+ }
- self.machine_st.lifted_heap.truncate(lh_offset);
+ Ok(())
+ }
- let solutions = self.machine_st.registers[2];
- unify_fn!(self.machine_st, heap_loc_as_cell!(h), solutions);
- }
- }
- &SystemClauseType::GetDoubleQuotes => {
- let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ #[inline(always)]
+ pub(crate) fn reset_block(&mut self) {
+ let addr = self.machine_st.deref(self.machine_st.registers[1]);
+ self.machine_st.reset_block(addr);
+ }
- self.machine_st.unify_atom(
- match self.machine_st.flags.double_quotes {
- DoubleQuotes::Chars => atom!("chars"),
- DoubleQuotes::Atom => atom!("atom"),
- DoubleQuotes::Codes => atom!("codes"),
- },
- a1,
- );
- }
- &SystemClauseType::GetSCCCleaner => {
- let dest = self.machine_st.registers[1];
+ #[inline(always)]
+ pub(crate) fn reset_continuation_marker(&mut self) {
+ let h = self.machine_st.heap.len();
- if let Some((addr, b_cutoff, prev_b)) = self.machine_st.cont_pts.pop() {
- let b = self.machine_st.stack.index_or_frame(self.machine_st.b).prelude.b;
+ self.machine_st.registers[3] = atom_as_cell!(atom!("none"));
+ self.machine_st.registers[4] = heap_loc_as_cell!(h);
- if b <= b_cutoff {
- self.machine_st.block = prev_b;
+ self.machine_st.heap.push(heap_loc_as_cell!(h));
+ }
- if let Some(r) = dest.as_var() {
- self.machine_st.bind(r, addr);
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- } else {
- self.machine_st.cont_pts.push((addr, b_cutoff, prev_b));
- }
- }
+ #[inline(always)]
+ pub(crate) fn set_ball(&mut self) {
+ self.machine_st.set_ball();
+ }
+ #[inline(always)]
+ pub(crate) fn set_seed(&mut self) {
+ let seed = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let mut rand = RANDOM_STATE.borrow_mut();
+
+ match Number::try_from(seed) {
+ Ok(Number::Fixnum(n)) => rand.seed(&Integer::from(n)),
+ Ok(Number::Integer(n)) => rand.seed(&*n),
+ Ok(Number::Rational(n)) if n.denom() == &1 => rand.seed(n.numer()),
+ _ => {
self.machine_st.fail = true;
}
- &SystemClauseType::Halt => {
- let code = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
-
- let code = match Number::try_from(code) {
- Ok(Number::Fixnum(n)) => i32::try_from(n.get_num()).unwrap(),
- Ok(Number::Integer(n)) => n.to_i32().unwrap(),
- Ok(Number::Rational(r)) => {
- // n has already been confirmed as an integer, and
- // internally, Rational is assumed reduced, so its
- // denominator must be 1.
- r.numer().to_i32().unwrap()
- }
- _ => {
- unreachable!()
- }
- };
+ }
+ }
- std::process::exit(code);
+ #[inline(always)]
+ pub(crate) fn sleep(&mut self) {
+ let time = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+
+ let time = match Number::try_from(time) {
+ Ok(Number::Float(n)) => n.into_inner(),
+ Ok(Number::Fixnum(n)) => n.get_num() as f64,
+ Ok(Number::Integer(n)) => n.to_f64(),
+ _ => {
+ unreachable!()
}
- &SystemClauseType::InstallSCCCleaner => {
- let addr = self.machine_st.registers[1];
- let b = self.machine_st.b;
- let prev_block = self.machine_st.block;
+ };
- self.machine_st.run_cleaners_fn = Machine::run_cleaners;
+ let duration = Duration::new(1, 0);
+ let duration = duration.mul_f64(time);
- self.machine_st.install_new_block(self.machine_st.registers[2]);
- self.machine_st.cont_pts.push((addr, b, prev_block));
- }
- &SystemClauseType::InstallInferenceCounter => {
- // A1 = B, A2 = L
- let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ std::thread::sleep(duration);
+ }
+
+ #[inline(always)]
+ pub(crate) fn socket_client_open(&mut self) -> CallResult {
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let port = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+
+ let socket_atom = cell_as_atom!(addr);
- let n = match Number::try_from(a2) {
- Ok(Number::Fixnum(bp)) => bp.get_num() as usize,
- Ok(Number::Integer(n)) => n.to_usize().unwrap(),
+ let _port = read_heap_cell!(port,
+ (HeapCellValueTag::Atom, (name, arity)) => {
+ debug_assert_eq!(arity, 0);
+ name
+ }
+ _ => {
+ self.machine_st.atom_tbl.build_with(&match Number::try_from(port) {
+ Ok(Number::Fixnum(n)) => n.get_num().to_string(),
+ Ok(Number::Integer(n)) => n.to_string(),
_ => {
- let stub = functor_stub(
- atom!("call_with_inference_limit"),
- 3,
- );
-
- let err = self.machine_st.type_error(ValidType::Integer, a2);
- return Err(self.machine_st.error_form(err, stub));
+ unreachable!()
}
- };
+ })
+ }
+ );
- let bp = cell_as_fixnum!(a1).get_num() as usize;
- let count = self.machine_st.cwil.add_limit(n, bp);
- let count = arena_alloc!(count.clone(), &mut self.machine_st.arena);
+ let socket_addr = if socket_atom == atom!("") {
+ atom!("127.0.0.1")
+ } else {
+ socket_atom
+ };
- self.machine_st.increment_call_count_fn = MachineState::increment_call_count;
+ let alias = self.machine_st.registers[4];
+ let eof_action = self.machine_st.registers[5];
+ let reposition = self.machine_st.registers[6];
+ let stream_type = self.machine_st.registers[7];
- let a3 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3]));
- self.machine_st.unify_big_int(count, a3);
- }
- &SystemClauseType::ModuleExists => {
- let module = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let module_name = cell_as_atom!(module);
+ let options = self.machine_st.to_stream_options(alias, eof_action, reposition, stream_type);
+
+ if options.reposition() {
+ return Err(self.machine_st.reposition_error(atom!("socket_client_open"), 3));
+ }
- self.machine_st.fail = !self.indices.modules.contains_key(&module_name);
+ if let Some(alias) = options.get_alias() {
+ if self.indices.stream_aliases.contains_key(&alias) {
+ return Err(self.machine_st.occupied_alias_permission_error(
+ alias,
+ atom!("socket_client_open"),
+ 3,
+ ));
}
- &SystemClauseType::NoSuchPredicate => {
- let module_name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])));
- let head = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ }
- self.machine_st.fail = read_heap_cell!(head,
- (HeapCellValueTag::Str, s) => {
- let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
- .get_name_and_arity();
+ let stream = match TcpStream::connect(socket_addr.as_str()).map_err(|e| e.kind()) {
+ Ok(tcp_stream) => {
+ let mut stream = {
+ let tls = cell_as_atom!(self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[8]
+ )));
- if clause_type_form(name, arity).is_some() {
- true
- } else {
- let index = self.indices.get_predicate_code_index(
- name,
- arity,
- module_name,
- )
- .map(|index| index.get())
- .unwrap_or(IndexPtr::DynamicUndefined);
-
- match index {
- IndexPtr::DynamicUndefined | IndexPtr::Undefined => false,
- _ => true,
- }
+ match tls {
+ atom!("false") => {
+ Stream::from_tcp_stream(socket_addr, tcp_stream, &mut self.machine_st.arena)
}
- }
- (HeapCellValueTag::Atom, (name, arity)) => {
- debug_assert_eq!(arity, 0);
+ atom!("true") => {
+ let connector = TlsConnector::new().unwrap();
+ let stream = Stream::from_tcp_stream(
+ socket_addr,
+ tcp_stream,
+ &mut self.machine_st.arena,
+ );
- if clause_type_form(name, 0).is_some() {
- true
- } else {
- let index = self.indices.get_predicate_code_index(
- name,
- 0,
- module_name,
- )
- .map(|index| index.get())
- .unwrap_or(IndexPtr::DynamicUndefined);
-
- match index {
- IndexPtr::DynamicUndefined => false,
- _ => true,
- }
- }
- }
- _ => {
- let err = self.machine_st.type_error(ValidType::Callable, head);
- let stub = functor_stub(atom!("clause"), 2);
+ let stream =
+ match connector.connect(socket_atom.as_str(), stream) {
+ Ok(tls_stream) => tls_stream,
+ Err(_) => {
+ return Err(self.machine_st.open_permission_error(
+ addr,
+ atom!("socket_client_open"),
+ 3,
+ ));
+ }
+ };
- return Err(self.machine_st.error_form(err, stub));
+ Stream::from_tls_stream(atom!("TLS"), stream, &mut self.machine_st.arena)
+ }
+ _ => {
+ unreachable!()
+ }
}
- );
- }
- &SystemClauseType::RedoAttrVarBinding => {
- let var = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let value = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ };
- debug_assert_eq!(HeapCellValueTag::AttrVar, var.get_tag());
- self.machine_st.heap[var.get_value()] = value;
- }
- &SystemClauseType::ResetAttrVarState => {
- self.machine_st.attr_var_init.reset();
- }
- &SystemClauseType::RemoveCallPolicyCheck => {
- let bp = cell_as_fixnum!(self.machine_st.store(self.machine_st.deref(
- self.machine_st.registers[1]
- ))).get_num() as usize;
+ *stream.options_mut() = options;
- if bp == self.machine_st.b && self.machine_st.cwil.is_empty() {
- self.machine_st.cwil.reset();
- self.machine_st.increment_call_count_fn = |_| { Ok(()) };
+ if let Some(alias) = stream.options().get_alias() {
+ self.indices.stream_aliases.insert(alias, stream);
}
- }
- &SystemClauseType::RemoveInferenceCounter => {
- let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let bp = cell_as_fixnum!(a1).get_num() as usize;
-
- let count = self.machine_st.cwil.remove_limit(bp).clone();
- let count = arena_alloc!(count.clone(), &mut self.machine_st.arena);
- let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ self.indices.streams.insert(stream);
- self.machine_st.unify_big_int(count, a2);
+ stream_as_cell!(stream)
}
- &SystemClauseType::REPL(repl_code_ptr) => {
- return self.machine_st.repl_redirect(repl_code_ptr);
+ Err(ErrorKind::PermissionDenied) => {
+ return Err(self.machine_st.open_permission_error(addr, atom!("socket_client_open"), 3));
}
- &SystemClauseType::ReturnFromVerifyAttr => {
- let e = self.machine_st.e;
- let frame_len = self.machine_st.stack.index_and_frame(e).prelude.univ_prelude.num_cells;
+ Err(ErrorKind::NotFound) => {
+ let stub = functor_stub(atom!("socket_client_open"), 3);
+ let err = self.machine_st.existence_error(
+ ExistenceError::SourceSink(addr),
+ );
- for i in 1..frame_len - 1 {
- self.machine_st.registers[i] = self.machine_st.stack[stack_loc!(AndFrame, e, i)];
- }
+ return Err(self.machine_st.error_form(err, stub));
+ }
+ Err(_) => {
+ // for now, just fail. expand to meaningful error messages later.
+ self.machine_st.fail = true;
+ return Ok(());
+ }
+ };
- self.machine_st.b0 = cell_as_fixnum!(self.machine_st.stack[stack_loc!(AndFrame, e, frame_len - 1)])
- .get_num() as usize;
+ let stream_addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3]));
+ self.machine_st.bind(stream_addr.as_var().unwrap(), stream);
- self.machine_st.num_of_args = cell_as_fixnum!(self.machine_st.stack[stack_loc!(AndFrame, e, frame_len)])
- .get_num() as usize;
+ Ok(())
+ }
- self.machine_st.deallocate();
- self.machine_st.p = CodePtr::Local(self.machine_st.stack.index_and_frame(e).prelude.interrupt_cp);
+ #[inline(always)]
+ pub(crate) fn socket_server_open(&mut self) -> CallResult {
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let socket_atom = cell_as_atom_cell!(addr).get_name();
- return Ok(());
- }
- &SystemClauseType::RestoreCutPolicy => {
- if self.machine_st.cont_pts.is_empty() {
- self.machine_st.run_cleaners_fn = |_| { false };
- }
- }
- &SystemClauseType::SetCutPoint(r) => {
- let cp = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
- self.machine_st.cut_body(cp);
+ let socket_atom = if socket_atom == atom!("[]") {
+ atom!("127.0.0.1")
+ } else {
+ socket_atom
+ };
- if (self.machine_st.run_cleaners_fn)(self) {
- return Ok(());
- }
- }
- &SystemClauseType::SetCutPointByDefault(r) => {
- let cp = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
- self.machine_st.cut_body(cp);
- }
- &SystemClauseType::SetInput => {
- let addr = self.machine_st.store(self.machine_st.deref(
- self.machine_st.registers[1]
- ));
- let stream = self.machine_st.get_stream_or_alias(
- addr,
- &self.indices.stream_aliases,
- atom!("set_input"),
- 1,
- )?;
-
- if !stream.is_input_stream() {
- let stub = functor_stub(atom!("set_input"), 1);
- let user_alias = atom_as_cell!(atom!("user"));
-
- let err = self.machine_st.permission_error(
- Permission::InputStream,
- atom!("stream"),
- user_alias,
- );
+ let port = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
- return Err(self.machine_st.error_form(err, stub));
+ let port = if port.is_var() {
+ String::from("0")
+ } else {
+ match Number::try_from(port) {
+ Ok(Number::Fixnum(n)) => n.get_num().to_string(),
+ Ok(Number::Integer(n)) => n.to_string(),
+ _ => {
+ unreachable!()
}
-
- self.user_input = stream;
}
- &SystemClauseType::SetOutput => {
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let stream = self.machine_st.get_stream_or_alias(
- addr,
- &self.indices.stream_aliases,
- atom!("set_output"),
- 1,
- )?;
-
- if !stream.is_output_stream() {
- let stub = functor_stub(atom!("set_input"), 1);
+ };
- let user_alias = atom_as_cell!(atom!("user"));
- let err = self.machine_st.permission_error(
- Permission::OutputStream,
- atom!("stream"),
- user_alias,
- );
+ let had_zero_port = &port == "0";
- return Err(self.machine_st.error_form(err, stub));
- }
+ let server_addr = if socket_atom == atom!("") {
+ port
+ } else {
+ format!("{}:{}", socket_atom.as_str(), port)
+ };
- self.user_output = stream;
- }
- &SystemClauseType::SetDoubleQuotes => {
- let atom = cell_as_atom!(self.machine_st.registers[1]);
+ let (tcp_listener, port) =
+ match TcpListener::bind(server_addr).map_err(|e| e.kind()) {
+ Ok(tcp_listener) => {
+ let port = tcp_listener.local_addr().map(|addr| addr.port()).ok();
- self.machine_st.flags.double_quotes = match atom {
- atom!("atom") => DoubleQuotes::Atom,
- atom!("chars") => DoubleQuotes::Chars,
- atom!("codes") => DoubleQuotes::Codes,
- _ => {
+ if let Some(port) = port {
+ (arena_alloc!(tcp_listener, &mut self.machine_st.arena), port as usize)
+ } else {
self.machine_st.fail = true;
return Ok(());
}
- };
- }
- &SystemClauseType::InferenceLevel => {
- let a1 = self.machine_st.registers[1];
- let a2 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
-
- let bp = cell_as_fixnum!(a2).get_num() as usize;
- let prev_b = self.machine_st.stack.index_or_frame(self.machine_st.b).prelude.b;
-
- if prev_b <= bp {
- self.machine_st.unify_atom(atom!("!"), a1)
- } else {
- self.machine_st.unify_atom(atom!("true"), a1);
}
- }
- &SystemClauseType::CleanUpBlock => {
- let nb = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let nb = cell_as_fixnum!(nb).get_num() as usize;
-
- let b = self.machine_st.b;
-
- if nb > 0 && self.machine_st.stack.index_or_frame(b).prelude.b == nb {
- self.machine_st.b = self.machine_st.stack.index_or_frame(nb).prelude.b;
+ Err(ErrorKind::PermissionDenied) => {
+ return Err(self.machine_st.open_permission_error(addr, atom!("socket_server_open"), 2));
}
- }
- &SystemClauseType::EraseBall => {
- self.machine_st.ball.reset();
- }
- &SystemClauseType::Fail => {
- self.machine_st.fail = true;
- }
- &SystemClauseType::GetBall => {
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let h = self.machine_st.heap.len();
-
- if self.machine_st.ball.stub.len() > 0 {
- let stub = self.machine_st.ball.copy_and_align(h);
- self.machine_st.heap.extend(stub.into_iter());
- } else {
+ _ => {
self.machine_st.fail = true;
return Ok(());
}
+ };
- match addr.as_var() {
- Some(r) => self.machine_st.bind(r, self.machine_st.heap[h]),
- _ => self.machine_st.fail = true,
- };
- }
- &SystemClauseType::GetCurrentBlock => {
- let n = Fixnum::build_with(i64::try_from(self.machine_st.block).unwrap());
- self.machine_st.unify_fixnum(n, self.machine_st.registers[1]);
- }
- &SystemClauseType::GetBValue => {
- let n = Fixnum::build_with(i64::try_from(self.machine_st.b).unwrap());
- self.machine_st.unify_fixnum(n, self.machine_st.registers[1]);
- }
- &SystemClauseType::GetCutPoint => {
- let n = Fixnum::build_with(i64::try_from(self.machine_st.b0).unwrap());
- self.machine_st.unify_fixnum(n, self.machine_st.registers[1]);
- }
- &SystemClauseType::GetStaggeredCutPoint => {
- use std::sync::Once;
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3]));
+ self.machine_st.bind(addr.as_var().unwrap(), typed_arena_ptr_as_cell!(tcp_listener));
- let b = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ if had_zero_port {
+ self.machine_st.unify_fixnum(Fixnum::build_with(port as i64), self.machine_st.registers[2]);
+ }
- static mut SEMICOLON_SECOND_BRANCH_LOC: usize = 0;
- static LOC_INIT: Once = Once::new();
+ Ok(())
+ }
- let semicolon_second_clause_p = unsafe {
- LOC_INIT.call_once(|| {
- match self.indices.code_dir.get(&(atom!(";"), 2)).map(|cell| cell.get()) {
- Some(IndexPtr::Index(p)) => {
- match self.code_repo.code[p] {
- Line::Choice(ChoiceInstruction::TryMeElse(o)) => {
- SEMICOLON_SECOND_BRANCH_LOC = p + o;
- }
- _ => {
- unreachable!();
- }
- }
- }
- _ => {
- unreachable!();
- }
- }
- });
+ #[inline(always)]
+ pub(crate) fn socket_server_accept(&mut self) -> CallResult {
+ let alias = self.machine_st.registers[4];
+ let eof_action = self.machine_st.registers[5];
+ let reposition = self.machine_st.registers[6];
+ let stream_type = self.machine_st.registers[7];
- LocalCodePtr::DirEntry(SEMICOLON_SECOND_BRANCH_LOC)
- };
+ let options = self.machine_st.to_stream_options(alias, eof_action, reposition, stream_type);
- let staggered_b0 = if self.machine_st.b > 0 {
- let or_frame = self.machine_st.stack.index_or_frame(self.machine_st.b);
+ if options.reposition() {
+ return Err(self.machine_st.reposition_error(atom!("socket_server_accept"), 4));
+ }
- if or_frame.prelude.bp == semicolon_second_clause_p {
- or_frame.prelude.b0
- } else {
- self.machine_st.b0
- }
- } else {
- self.machine_st.b0
- };
+ if let Some(alias) = options.get_alias() {
+ if self.indices.stream_aliases.contains_key(&alias) {
+ return Err(self.machine_st.occupied_alias_permission_error(
+ alias,
+ atom!("socket_server_accept"),
+ 4,
+ ));
+ }
+ }
- let staggered_b0 = integer_as_cell!(
- Number::arena_from(staggered_b0, &mut self.machine_st.arena)
- );
+ let culprit = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- self.machine_st.bind(b.as_var().unwrap(), staggered_b0);
- }
- &SystemClauseType::InstallNewBlock => {
- self.machine_st.install_new_block(self.machine_st.registers[1]);
- }
- &SystemClauseType::NextEP => {
- let first_arg = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ read_heap_cell!(culprit,
+ (HeapCellValueTag::Cons, cons_ptr) => {
+ match_untyped_arena_ptr!(cons_ptr,
+ (ArenaHeaderTag::TcpListener, tcp_listener) => {
+ match tcp_listener.accept().ok() {
+ Some((tcp_stream, socket_addr)) => {
+ let client = self.machine_st.atom_tbl.build_with(&socket_addr.to_string());
- read_heap_cell!(first_arg,
- (HeapCellValueTag::Atom, (name, arity)) => {
- debug_assert_eq!(name, atom!("first"));
- debug_assert_eq!(arity, 0);
+ let mut tcp_stream = Stream::from_tcp_stream(
+ client,
+ tcp_stream,
+ &mut self.machine_st.arena,
+ );
- if self.machine_st.e == 0 {
- self.machine_st.fail = true;
- return Ok(());
- }
+ *tcp_stream.options_mut() = options;
- let and_frame = self.machine_st.stack.index_and_frame(self.machine_st.e);
- let cp = (and_frame.prelude.cp - 1).unwrap();
+ if let Some(alias) = &tcp_stream.options().get_alias() {
+ self.indices.stream_aliases.insert(*alias, tcp_stream);
+ }
- let e = and_frame.prelude.e;
- let e = Fixnum::build_with(i64::try_from(e).unwrap());
+ self.indices.streams.insert(tcp_stream);
- let p = str_loc_as_cell!(self.machine_st.heap.len());
+ let tcp_stream = stream_as_cell!(tcp_stream);
+ let client = atom_as_cell!(client);
- self.machine_st.heap.extend(cp.as_functor());
- self.machine_st.unify_fixnum(e, self.machine_st.registers[2]);
+ let client_addr = self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[2],
+ ));
+ let stream_addr = self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[3],
+ ));
- if !self.machine_st.fail {
- unify!(self.machine_st, p, self.machine_st.registers[3]);
- }
+ self.machine_st.bind(client_addr.as_var().unwrap(), client);
+ self.machine_st.bind(stream_addr.as_var().unwrap(), tcp_stream);
+ }
+ None => {
+ self.machine_st.fail = true;
+ }
+ }
+ }
+ _ => {
+ }
+ );
+ }
+ _ => {
+ }
+ );
+
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn tls_client_connect(&mut self) -> CallResult {
+ if let Some(hostname) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ let stream0 = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[2],
+ &self.indices.stream_aliases,
+ atom!("tls_client_negotiate"),
+ 3,
+ )?;
+
+ let connector = TlsConnector::new().unwrap();
+ let stream =
+ match connector.connect(hostname.as_str(), stream0) {
+ Ok(tls_stream) => tls_stream,
+ Err(_) => {
+ return Err(self.machine_st.open_permission_error(
+ self.machine_st.registers[1],
+ atom!("tls_client_negotiate"),
+ 3,
+ ));
}
- (HeapCellValueTag::Fixnum, n) => {
- let e = n.get_num() as usize;
+ };
- if e == 0 {
- self.machine_st.fail = true;
- return Ok(());
- }
+ let addr = atom!("TLS");
+ let stream = Stream::from_tls_stream(addr, stream, &mut self.machine_st.arena);
+ self.indices.streams.insert(stream);
- // get the call site so that the number of
- // active permanent variables can be read from
- // it later.
- let and_frame = self.machine_st.stack.index_and_frame(e);
- let cp = (and_frame.prelude.cp - 1).unwrap();
+ self.machine_st.heap.push(stream_as_cell!(stream));
+ let stream_addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3]));
+ self.machine_st.bind(stream_addr.as_var().unwrap(), stream_as_cell!(stream));
- let p = str_loc_as_cell!(self.machine_st.heap.len());
- self.machine_st.heap.extend(cp.as_functor());
+ Ok(())
+ } else {
+ unreachable!();
+ }
+ }
- let e = Fixnum::build_with(i64::try_from(and_frame.prelude.e).unwrap());
- self.machine_st.unify_fixnum(e, self.machine_st.registers[2]);
+ #[inline(always)]
+ pub(crate) fn tls_accept_client(&mut self) -> CallResult {
+ let pkcs12 = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
- if !self.machine_st.fail {
- unify!(self.machine_st, p, self.machine_st.registers[3]);
- }
- }
- _ => {
- unreachable!();
+ if let Some(password) = self.machine_st.value_to_str_like(self.machine_st.registers[2]) {
+ let identity =
+ match Identity::from_pkcs12(&pkcs12, password.as_str()) {
+ Ok(identity) => identity,
+ Err(_) => {
+ return Err(self.machine_st.open_permission_error(
+ self.machine_st.registers[1],
+ atom!("tls_server_negotiate"),
+ 3,
+ ));
}
- );
- }
- &SystemClauseType::PointsToContinuationResetMarker => {
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ };
- let p = match to_local_code_ptr(&self.machine_st.heap, addr) {
- Some(p) => p + 1,
- None => {
- self.machine_st.fail = true;
- return Ok(());
+ let stream0 = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[3],
+ &self.indices.stream_aliases,
+ atom!("tls_server_negotiate"),
+ 3,
+ )?;
+
+ let acceptor = TlsAcceptor::new(identity).unwrap();
+
+ let stream =
+ match acceptor.accept(stream0) {
+ Ok(tls_stream) => tls_stream,
+ Err(_) => {
+ return Err(self.machine_st.open_permission_error(
+ self.machine_st.registers[3],
+ atom!("tls_server_negotiate"),
+ 3,
+ ));
}
};
- if self.is_reset_cont_marker(p) {
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
+ let stream = Stream::from_tls_stream(atom!("TLS"), stream, &mut self.machine_st.arena);
+ self.indices.streams.insert(stream);
- self.machine_st.fail = true;
- return Ok(());
- }
- &SystemClauseType::QuotedToken => {
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let stream_addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[4]));
+ self.machine_st.bind(stream_addr.as_var().unwrap(), stream_as_cell!(stream));
+ } else {
+ unreachable!();
+ }
- read_heap_cell!(addr,
- (HeapCellValueTag::Fixnum, n) => {
- let n = u32::try_from(n.get_num()).ok();
- let n = n.and_then(std::char::from_u32);
+ Ok(())
+ }
- self.machine_st.fail = match n {
- Some(c) => non_quoted_token(once(c)),
- None => true,
- };
- }
- (HeapCellValueTag::Char, c) => {
- self.machine_st.fail = non_quoted_token(once(c));
- }
- (HeapCellValueTag::Atom, (name, arity)) => {
- debug_assert_eq!(arity, 0);
- self.machine_st.fail = non_quoted_token(name.as_str().chars());
+ #[inline(always)]
+ pub(crate) fn socket_server_close(&mut self) -> CallResult {
+ let culprit = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+
+ read_heap_cell!(culprit,
+ (HeapCellValueTag::Cons, cons_ptr) => {
+ match_untyped_arena_ptr!(cons_ptr,
+ (ArenaHeaderTag::TcpListener, tcp_listener) => {
+ unsafe {
+ // dropping closes the instance.
+ std::ptr::drop_in_place(&mut tcp_listener as *mut _);
+ }
+
+ tcp_listener.set_tag(ArenaHeaderTag::Dropped);
+ return Ok(());
}
_ => {
- self.machine_st.fail = true;
}
);
}
- &SystemClauseType::ReadQueryTerm => {
- self.user_input.reset();
-
- set_prompt(true);
- let result = self.machine_st.read_term(self.user_input, &mut self.indices);
- set_prompt(false);
-
- match result {
- Ok(()) => {}
- Err(e) => {
- self.user_input = input_stream(&mut self.machine_st.arena);
- return Err(e);
- }
- }
+ _ => {
}
- &SystemClauseType::ReadTerm => {
- set_prompt(false);
+ );
- let stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("read_term"),
- 3,
- )?;
+ let err = self.machine_st.type_error(ValidType::TcpListener, culprit);
+ let stub = functor_stub(atom!("socket_server_close"), 1);
- self.machine_st.read_term(stream, &mut self.indices)?;
- }
- &SystemClauseType::ReadTermFromChars => {
- if let Some(atom_or_string) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- let chars = atom_or_string.to_string();
- let stream = Stream::from_owned_string(chars, &mut self.machine_st.arena);
+ return Err(self.machine_st.error_form(err, stub));
+ }
- let term_write_result = match self.machine_st.read(stream, &self.indices.op_dir) {
- Ok(term_write_result) => term_write_result,
- Err(e) => {
- let stub = functor_stub(atom!("read_term_from_chars"), 2);
- let e = self.machine_st.session_error(SessionError::from(e));
+ #[inline(always)]
+ pub(crate) fn set_stream_position(&mut self) -> CallResult {
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("set_stream_position"),
+ 2,
+ )?;
+
+ if !stream.options().reposition() {
+ let stub = functor_stub(atom!("set_stream_position"), 2);
+
+ let err = self.machine_st.permission_error(
+ Permission::Reposition,
+ atom!("stream"),
+ vec![stream_as_cell!(stream)],
+ );
- return Err(self.machine_st.error_form(e, stub));
- }
- };
+ return Err(self.machine_st.error_form(err, stub));
+ }
- let result = heap_loc_as_cell!(term_write_result.heap_loc);
- let var = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])).as_var().unwrap();
+ let position = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
- self.machine_st.bind(var, result);
+ let position = match Number::try_from(position) {
+ Ok(Number::Fixnum(n)) => n.get_num() as u64,
+ Ok(Number::Integer(n)) => {
+ if let Some(n) = n.to_u64() {
+ n
} else {
- unreachable!()
+ self.machine_st.fail = true;
+ return Ok(());
}
}
- &SystemClauseType::ResetBlock => {
- let addr = self.machine_st.deref(self.machine_st.registers[1]);
- self.machine_st.reset_block(addr);
+ _ => {
+ unreachable!()
}
- &SystemClauseType::ResetContinuationMarker => {
- let h = self.machine_st.heap.len();
+ };
- self.machine_st.registers[3] = atom_as_cell!(atom!("none"));
- self.machine_st.registers[4] = heap_loc_as_cell!(h);
+ stream.set_position(position);
+ Ok(())
+ }
- self.machine_st.heap.push(heap_loc_as_cell!(h));
- }
- &SystemClauseType::SetBall => {
- self.machine_st.set_ball();
+ #[inline(always)]
+ pub(crate) fn stream_property(&mut self) -> CallResult {
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("stream_property"),
+ 2,
+ )?;
+
+ let atom = cell_as_atom!(self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[2]
+ )));
+
+ let property = match atom {
+ atom!("file_name") => {
+ atom_as_cell!(if let Some(file_name) = stream.file_name() {
+ file_name
+ } else {
+ self.machine_st.fail = true;
+ return Ok(());
+ })
+ }
+ atom!("mode") => atom_as_cell!(stream.mode()),
+ atom!("direction") =>
+ atom_as_cell!(if stream.is_input_stream() && stream.is_output_stream() {
+ atom!("input_output")
+ } else if stream.is_input_stream() {
+ atom!("input")
+ } else {
+ atom!("output")
+ }),
+ atom!("alias") => {
+ atom_as_cell!(if let Some(alias) = stream.options().get_alias() {
+ alias
+ } else {
+ self.machine_st.fail = true;
+ return Ok(());
+ })
}
- &SystemClauseType::SetSeed => {
- let seed = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let mut rand = RANDOM_STATE.borrow_mut();
+ atom!("position") => {
+ if let Some((position, lines_read)) = stream.position() {
+ let h = self.machine_st.heap.len();
- match Number::try_from(seed) {
- Ok(Number::Fixnum(n)) => rand.seed(&Integer::from(n)),
- Ok(Number::Integer(n)) => rand.seed(&*n),
- Ok(Number::Rational(n)) if n.denom() == &1 => rand.seed(n.numer()),
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
+ let position_term = functor!(
+ atom!("position_and_lines_read"),
+ [integer(position, &mut self.machine_st.arena),
+ integer(lines_read, &mut self.machine_st.arena)]
+ );
+
+ self.machine_st.heap.extend(position_term.into_iter());
+ str_loc_as_cell!(h)
+ } else {
+ self.machine_st.fail = true;
+ return Ok(());
}
}
- &SystemClauseType::SkipMaxList => {
- if let Err(err) = self.machine_st.skip_max_list() {
- return Err(err);
- }
+ atom!("end_of_stream") => {
+ let end_of_stream_pos = stream.position_relative_to_end();
+ atom_as_cell!(end_of_stream_pos.as_atom())
}
- &SystemClauseType::Sleep => {
- let time = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
-
- let time = match Number::try_from(time) {
- Ok(Number::Float(n)) => n.into_inner(),
- Ok(Number::Fixnum(n)) => n.get_num() as f64,
- Ok(Number::Integer(n)) => n.to_f64(),
- _ => {
- unreachable!()
- }
- };
-
- let duration = Duration::new(1, 0);
- let duration = duration.mul_f64(time);
-
- std::thread::sleep(duration);
+ atom!("eof_action") => {
+ atom_as_cell!(stream.options().eof_action().as_atom())
}
- &SystemClauseType::SocketClientOpen => {
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let port = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
-
- let socket_atom = cell_as_atom!(addr);
-
- let _port = read_heap_cell!(port,
- (HeapCellValueTag::Atom, (name, arity)) => {
- debug_assert_eq!(arity, 0);
- name
- }
- _ => {
- self.machine_st.atom_tbl.build_with(&match Number::try_from(port) {
- Ok(Number::Fixnum(n)) => n.get_num().to_string(),
- Ok(Number::Integer(n)) => n.to_string(),
- _ => {
- unreachable!()
- }
- })
- }
- );
-
- let socket_addr = if socket_atom == atom!("") {
- atom!("127.0.0.1")
- } else {
- socket_atom
- };
-
- let alias = self.machine_st.registers[4];
- let eof_action = self.machine_st.registers[5];
- let reposition = self.machine_st.registers[6];
- let stream_type = self.machine_st.registers[7];
+ atom!("reposition") =>
+ atom_as_cell!(if stream.options().reposition() {
+ atom!("true")
+ } else {
+ atom!("false")
+ }),
+ atom!("type") => {
+ atom_as_cell!(stream.options().stream_type().as_property_atom())
+ }
+ _ => {
+ unreachable!()
+ }
+ };
- let options = self.machine_st.to_stream_options(alias, eof_action, reposition, stream_type);
+ unify!(self.machine_st, property, self.machine_st.registers[3]);
+ Ok(())
+ }
- if options.reposition() {
- return Err(self.machine_st.reposition_error(atom!("socket_client_open"), 3));
- }
+ #[inline(always)]
+ pub(crate) fn store_global_var(&mut self) {
+ let key = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])));
- if let Some(alias) = options.get_alias() {
- if self.indices.stream_aliases.contains_key(&alias) {
- return Err(self.machine_st.occupied_alias_permission_error(
- alias,
- atom!("socket_client_open"),
- 3,
- ));
- }
- }
+ let value = self.machine_st.registers[2];
+ let mut ball = Ball::new();
- let stream = match TcpStream::connect(socket_addr.as_str()).map_err(|e| e.kind()) {
- Ok(tcp_stream) => {
- let mut stream = Stream::from_tcp_stream(socket_addr, tcp_stream, &mut self.arena);
+ ball.boundary = self.machine_st.heap.len();
- *stream.options_mut() = options;
+ copy_term(
+ CopyBallTerm::new(&mut self.machine_st.stack, &mut self.machine_st.heap, &mut ball.stub),
+ value,
+ AttrVarPolicy::DeepCopy,
+ );
- if let Some(alias) = stream.options().get_alias() {
- self.indices.stream_aliases.insert(alias, stream);
- }
+ self.indices.global_variables.insert(key, (ball, None));
+ }
- self.indices.streams.insert(stream);
+ #[inline(always)]
+ pub(crate) fn store_backtrackable_global_var(&mut self) {
+ let key = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])));
+ let new_value = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
- stream_as_cell!(stream)
- }
- Err(ErrorKind::PermissionDenied) => {
- return Err(self.machine_st.open_permission_error(addr, atom!("socket_client_open"), 3));
- }
- Err(ErrorKind::NotFound) => {
- let stub = functor_stub(atom!("socket_client_open"), 3);
- let err = self.machine_st.existence_error(
- ExistenceError::SourceSink(addr),
- );
+ match self.indices.global_variables.get_mut(&key) {
+ Some((_, ref mut loc)) => match loc {
+ Some(ref mut value) => {
+ self.machine_st.trail(TrailRef::BlackboardOffset(key, *value));
+ *value = new_value;
+ }
+ loc @ None => {
+ self.machine_st.trail(TrailRef::BlackboardEntry(key));
+ *loc = Some(new_value);
+ }
+ },
+ None => {
+ self.machine_st.trail(TrailRef::BlackboardEntry(key));
+ self.indices
+ .global_variables
+ .insert(key, (Ball::new(), Some(new_value)));
+ }
+ }
+ }
- return Err(self.machine_st.error_form(err, stub));
- }
- Err(_) => {
- // for now, just fail. expand to meaningful error messages later.
- self.machine_st.fail = true;
- return Ok(());
- }
- };
+ #[inline(always)]
+ pub(crate) fn term_attributed_variables(&mut self) {
+ if self.machine_st.registers[1].is_constant() {
+ self.machine_st.unify_atom(
+ atom!("[]"),
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])),
+ );
- let stream_addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3]));
- self.machine_st.bind(stream_addr.as_var().unwrap(), stream);
- }
- &SystemClauseType::SocketServerOpen => {
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let socket_atom = cell_as_atom_cell!(addr).get_name();
+ return;
+ }
- let socket_atom = if socket_atom == atom!("[]") {
- atom!("127.0.0.1")
- } else {
- socket_atom
- };
+ let seen_vars = self.machine_st.attr_vars_of_term(self.machine_st.registers[1]);
+ let outcome = heap_loc_as_cell!(
+ iter_to_heap_list(&mut self.machine_st.heap, seen_vars.into_iter())
+ );
- let port = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ unify_fn!(self.machine_st, self.machine_st.registers[2], outcome);
+ }
- let port = if port.is_var() {
- String::from("0")
- } else {
- match Number::try_from(port) {
- Ok(Number::Fixnum(n)) => n.get_num().to_string(),
- Ok(Number::Integer(n)) => n.to_string(),
- _ => {
- unreachable!()
- }
- }
- };
+ #[inline(always)]
+ pub(crate) fn term_variables(&mut self) {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
- let had_zero_port = &port == "0";
+ let stored_v = self.machine_st.store(self.machine_st.deref(a1));
- let server_addr = if socket_atom == atom!("") {
- port
- } else {
- format!("{}:{}", socket_atom.as_str(), port)
- };
+ if stored_v.is_constant() {
+ self.machine_st.unify_atom(atom!("[]"), self.machine_st.store(self.machine_st.deref(a2)));
+ return;
+ }
- let (tcp_listener, port) =
- match TcpListener::bind(server_addr).map_err(|e| e.kind()) {
- Ok(tcp_listener) => {
- let port = tcp_listener.local_addr().map(|addr| addr.port()).ok();
+ let mut seen_set = IndexSet::new();
- if let Some(port) = port {
- (arena_alloc!(tcp_listener, &mut self.machine_st.arena), port as usize)
- } else {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
- Err(ErrorKind::PermissionDenied) => {
- return Err(self.machine_st.open_permission_error(addr, atom!("socket_server_open"), 2));
- }
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- };
+ {
+ let mut iter = stackless_preorder_iter(&mut self.machine_st.heap, stored_v);
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3]));
- self.machine_st.bind(addr.as_var().unwrap(), typed_arena_ptr_as_cell!(tcp_listener));
+ while let Some(addr) = iter.next() {
+ let addr = unmark_cell_bits!(addr);
- if had_zero_port {
- self.machine_st.unify_fixnum(Fixnum::build_with(port as i64), self.machine_st.registers[2]);
+ if addr.is_var() {
+ seen_set.insert(addr);
}
}
- &SystemClauseType::SocketServerAccept => {
- let alias = self.machine_st.registers[4];
- let eof_action = self.machine_st.registers[5];
- let reposition = self.machine_st.registers[6];
- let stream_type = self.machine_st.registers[7];
+ }
- let options = self.machine_st.to_stream_options(alias, eof_action, reposition, stream_type);
+ let outcome = heap_loc_as_cell!(
+ filtered_iter_to_heap_list(
+ &mut self.machine_st.heap,
+ seen_set.into_iter().rev(),
+ |heap, value| {
+ heap_bound_store(
+ heap,
+ heap_bound_deref(heap, value),
+ ).is_var()
+ },
+ )
+ );
- if options.reposition() {
- return Err(self.machine_st.reposition_error(atom!("socket_server_accept"), 4));
- }
+ unify_fn!(self.machine_st, a2, outcome);
+ }
- if let Some(alias) = options.get_alias() {
- if self.indices.stream_aliases.contains_key(&alias) {
- return Err(self.machine_st.occupied_alias_permission_error(
- alias,
- atom!("socket_server_accept"),
- 4,
- ));
- }
- }
+ #[inline(always)]
+ pub(crate) fn term_variables_under_max_depth(&mut self) {
+ // Term, MaxDepth, VarList
+ let max_depth = cell_as_fixnum!(
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]))
+ ).get_num() as usize;
+
+ self.machine_st.term_variables_under_max_depth(
+ self.machine_st.registers[1],
+ max_depth,
+ self.machine_st.registers[3],
+ );
+ }
- let culprit = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ #[inline(always)]
+ pub(crate) fn truncate_lifted_heap_to(&mut self) {
+ let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let lh_offset = cell_as_fixnum!(a1).get_num() as usize;
- read_heap_cell!(culprit,
- (HeapCellValueTag::Cons, cons_ptr) => {
- match_untyped_arena_ptr!(cons_ptr,
- (ArenaHeaderTag::TcpListener, tcp_listener) => {
- match tcp_listener.accept().ok() {
- Some((tcp_stream, socket_addr)) => {
- let client = self.machine_st.atom_tbl.build_with(&socket_addr.to_string());
+ self.machine_st.lifted_heap.truncate(lh_offset);
+ }
- let mut tcp_stream = Stream::from_tcp_stream(
- client,
- tcp_stream,
- &mut self.machine_st.arena,
- );
+ #[inline(always)]
+ pub(crate) fn unify_with_occurs_check(&mut self) {
+ let a1 = self.machine_st.registers[1];
+ let a2 = self.machine_st.registers[2];
- *tcp_stream.options_mut() = options;
+ unify_with_occurs_check!(&mut self.machine_st, a1, a2);
+ }
- if let Some(alias) = &tcp_stream.options().get_alias() {
- self.indices.stream_aliases.insert(*alias, tcp_stream);
- }
+ #[inline(always)]
+ pub(crate) fn unwind_environments(&mut self) -> bool {
+ let mut e = self.machine_st.e;
+ let mut cp = self.machine_st.cp;
- self.indices.streams.insert(tcp_stream);
+ while e > 0 {
+ if self.is_reset_cont_marker(cp) {
+ self.machine_st.e = e;
+ self.machine_st.p = cp + 1; // skip the reset marker.
- let tcp_stream = stream_as_cell!(tcp_stream);
- let client = atom_as_cell!(client);
+ return true;
+ }
- let client_addr = self.machine_st.store(self.machine_st.deref(
- self.machine_st.registers[2],
- ));
- let stream_addr = self.machine_st.store(self.machine_st.deref(
- self.machine_st.registers[3],
- ));
+ let and_frame = self.machine_st.stack.index_and_frame(e);
- self.machine_st.bind(client_addr.as_var().unwrap(), client);
- self.machine_st.bind(stream_addr.as_var().unwrap(), tcp_stream);
+ cp = and_frame.prelude.cp;
+ e = and_frame.prelude.e;
+ }
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- None => {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
- }
- _ => {
- }
- );
- }
- _ => {
- }
- );
- }
- &SystemClauseType::TLSClientConnect => {
- if let Some(hostname) = self.value_to_str_like(self.registers[1]) {
- let stream0 = self.get_stream_or_alias(
- self.registers[2],
- &indices.stream_aliases,
- atom!("tls_client_negotiate"),
- 3,
- )?;
+ false
+ }
- let connector = TlsConnector::new().unwrap();
- let stream =
- match connector.connect(hostname.as_str(), stream0) {
- Ok(tls_stream) => tls_stream,
- Err(_) => {
- return Err(self.open_permission_error(
- self[temp_v!(1)],
- atom!("tls_client_negotiate"),
- 3,
- ));
- }
- };
+ #[inline(always)]
+ pub(crate) fn wam_instructions(&mut self) -> CallResult {
+ let module_name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[1])
+ ));
- let addr = atom!("TLS");
- let stream = Stream::from_tls_stream(addr, stream, &mut self.arena);
- indices.streams.insert(stream);
+ let name = self.machine_st.registers[2];
+ let arity = self.machine_st.registers[3];
- self.heap.push(stream_as_cell!(stream));
- let stream_addr = self.store(self.deref(self.registers[3]));
- self.bind(stream_addr.as_var().unwrap(), stream_as_cell!(stream));
- } else {
- unreachable!();
- }
- }
- &SystemClauseType::TLSAcceptClient => {
- let pkcs12 = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
-
- if let Some(password) = self.machine_st.value_to_str_like(self.machine_st.registers[2]) {
- let identity =
- match Identity::from_pkcs12(&pkcs12, password.as_str()) {
- Ok(identity) => identity,
- Err(_) => {
- return Err(self.machine_st.open_permission_error(
- self.machine_st.registers[1],
- atom!("tls_server_negotiate"),
- 3,
- ));
- }
- };
+ let name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(name)));
+ let arity = self.machine_st.store(self.machine_st.deref(arity));
- let stream0 = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[3],
- &self.indices.stream_aliases,
- atom!("tls_server_negotiate"),
- 3,
- )?;
+ let arity = match Number::try_from(arity) {
+ Ok(Number::Fixnum(n)) => n.get_num() as usize,
+ Ok(Number::Integer(n)) => n.to_usize().unwrap(),
+ _ => {
+ unreachable!()
+ }
+ };
- let acceptor = TlsAcceptor::new(identity).unwrap();
-
- let stream =
- match acceptor.accept(stream0) {
- Ok(tls_stream) => tls_stream,
- Err(_) => {
- return Err(self.machine_st.open_permission_error(
- self.machine_st.registers[3],
- atom!("tls_server_negotiate"),
- 3,
- ));
- }
- };
+ let key = (name, arity);
+
+ let first_idx = match module_name {
+ atom!("user") => self.indices.code_dir.get(&key),
+ _ => match self.indices.modules.get(&module_name) {
+ Some(module) => module.code_dir.get(&key),
+ None => {
+ let stub = functor_stub(key.0, key.1);
+ let err = self.machine_st.session_error(
+ SessionError::from(CompilationError::InvalidModuleResolution(
+ module_name,
+ )),
+ );
- let stream = Stream::from_tls_stream(atom!("TLS"), stream, &mut self.machine_st.arena);
- self.indices.streams.insert(stream);
+ return Err(self.machine_st.error_form(err, stub));
+ }
+ },
+ };
- let stream_addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[4]));
- self.machine_st.bind(stream_addr.as_var().unwrap(), stream_as_cell!(stream));
+ let first_idx = match first_idx {
+ Some(ref idx) if idx.local().is_some() => {
+ if let Some(idx) = idx.local() {
+ idx
} else {
- unreachable!();
+ unreachable!()
}
}
- &SystemClauseType::SocketServerClose => {
- let culprit = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
-
- read_heap_cell!(culprit,
- (HeapCellValueTag::Cons, cons_ptr) => {
- match_untyped_arena_ptr!(cons_ptr,
- (ArenaHeaderTag::TcpListener, tcp_listener) => {
- unsafe {
- // dropping closes the instance.
- std::ptr::drop_in_place(&mut tcp_listener as *mut _);
- }
-
- tcp_listener.set_tag(ArenaHeaderTag::Dropped);
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- _ => {
- }
- );
- }
- _ => {
- }
+ _ => {
+ let stub = functor_stub(name, arity);
+ let err = self.machine_st.existence_error(
+ ExistenceError::Procedure(name, arity),
);
- let err = self.machine_st.type_error(ValidType::TcpListener, culprit);
- let stub = functor_stub(atom!("socket_server_close"), 1);
-
return Err(self.machine_st.error_form(err, stub));
}
- &SystemClauseType::SetStreamPosition => {
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("set_stream_position"),
- 2,
- )?;
-
- if !stream.options().reposition() {
- let stub = functor_stub(atom!("set_stream_position"), 2);
-
- let err = self.machine_st.permission_error(
- Permission::Reposition,
- atom!("stream"),
- vec![stream_as_cell!(stream)],
- );
+ };
- return Err(self.machine_st.error_form(err, stub));
- }
+ let mut h = self.machine_st.heap.len();
- let position = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ let mut functors = vec![];
+ let mut functor_list = vec![];
- let position = match Number::try_from(position) {
- Ok(Number::Fixnum(n)) => n.get_num() as u64,
- Ok(Number::Integer(n)) => {
- if let Some(n) = n.to_u64() {
- n
- } else {
- self.machine_st.fail = true;
- return Ok(());
- }
+ walk_code(&self.code, first_idx, |instr| {
+ let old_len = functors.len();
+ instr.enqueue_functors(h, &mut self.machine_st.arena, &mut functors);
+ let new_len = functors.len();
+
+ for index in old_len..new_len {
+ let functor_len = functors[index].len();
+
+ match functor_len {
+ 0 => {}
+ 1 => {
+ functor_list.push(heap_loc_as_cell!(h));
+ h += functor_len;
}
_ => {
- unreachable!()
+ functor_list.push(str_loc_as_cell!(h));
+ h += functor_len;
}
- };
-
- stream.set_position(position);
+ }
}
- &SystemClauseType::StreamProperty => {
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("stream_property"),
- 2,
- )?;
+ });
- let atom = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])));
+ for functor in functors {
+ self.machine_st.heap.extend(functor.into_iter());
+ }
- let property = match atom {
- atom!("file_name") => {
- atom_as_cell!(if let Some(file_name) = stream.file_name() {
- file_name
- } else {
- self.machine_st.fail = true;
- return Ok(());
- })
- }
- atom!("mode") => atom_as_cell!(stream.mode()),
- atom!("direction") =>
- atom_as_cell!(if stream.is_input_stream() && stream.is_output_stream() {
- atom!("input_output")
- } else if stream.is_input_stream() {
- atom!("input")
- } else {
- atom!("output")
- }),
- atom!("alias") => {
- atom_as_cell!(if let Some(alias) = stream.options().get_alias() {
- alias
- } else {
- self.machine_st.fail = true;
- return Ok(());
- })
- }
- atom!("position") => {
- if let Some((position, lines_read)) = stream.position() {
- let h = self.machine_st.heap.len();
-
- let position_term = functor!(
- atom!("position_and_lines_read"),
- [integer(position, &mut self.machine_st.arena),
- integer(lines_read, &mut self.machine_st.arena)]
- );
+ let listing = heap_loc_as_cell!(
+ iter_to_heap_list(&mut self.machine_st.heap, functor_list.into_iter())
+ );
- self.machine_st.heap.extend(position_term.into_iter());
- str_loc_as_cell!(h)
- } else {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
- atom!("end_of_stream") => {
- let end_of_stream_pos = stream.position_relative_to_end();
- atom_as_cell!(end_of_stream_pos.as_atom())
- }
- atom!("eof_action") => {
- atom_as_cell!(stream.options().eof_action().as_atom())
- }
- atom!("reposition") =>
- atom_as_cell!(if stream.options().reposition() {
- atom!("true")
- } else {
- atom!("false")
- }),
- atom!("type") => {
- atom_as_cell!(stream.options().stream_type().as_property_atom())
- }
- _ => {
- unreachable!()
- }
- };
+ let listing_var = self.machine_st.registers[4];
- unify!(self.machine_st, property, self.machine_st.registers[3]);
- }
- &SystemClauseType::StoreGlobalVar => {
- let key = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])));
+ unify!(self.machine_st, listing, listing_var);
+ Ok(())
+ }
- let value = self.machine_st.registers[2];
- let mut ball = Ball::new();
+ #[inline(always)]
+ pub(crate) fn write_term(&mut self) -> CallResult {
+ let mut stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("write_term"),
+ 3,
+ )?;
+
+ self.machine_st.check_stream_properties(
+ stream,
+ StreamType::Text,
+ None, // input
+ atom!("write_term"),
+ 3,
+ )?;
+
+ let opt_err = if !stream.is_output_stream() {
+ Some(atom!("stream")) // 8.14.2.3 g)
+ } else if stream.options().stream_type() == StreamType::Binary {
+ Some(atom!("binary_stream")) // 8.14.2.3 h)
+ } else {
+ None
+ };
- ball.boundary = self.machine_st.heap.len();
+ if let Some(err_atom) = opt_err {
+ return Err(self.machine_st.stream_permission_error(
+ Permission::OutputStream,
+ err_atom,
+ stream,
+ atom!("write_term"),
+ 3,
+ ));
+ }
- copy_term(
- CopyBallTerm::new(&mut self.machine_st.stack, &mut self.machine_st.heap, &mut ball.stub),
- value,
- AttrVarPolicy::DeepCopy,
- );
+ let printer = match self.machine_st.write_term(&self.indices.op_dir)? {
+ Some(printer) => printer,
+ None => {
+ // this next line is executed by
+ // MachineState::write_term in this case. it's
+ // commented here because rustc can't prove
+ // that it's no longer borrowed.
- self.indices.global_variables.insert(key, (ball, None));
+ // self.machine_st.fail = true;
+ return Ok(());
}
- &SystemClauseType::StoreBacktrackableGlobalVar => {
- let key = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])));
- let new_value = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ };
- match self.indices.global_variables.get_mut(&key) {
- Some((_, ref mut loc)) => match loc {
- Some(ref mut value) => {
- self.machine_st.trail(TrailRef::BlackboardOffset(key, *value));
- *value = new_value;
- }
- loc @ None => {
- self.machine_st.trail(TrailRef::BlackboardEntry(key));
- *loc = Some(new_value);
- }
- },
- None => {
- self.machine_st.trail(TrailRef::BlackboardEntry(key));
- self.indices
- .global_variables
- .insert(key, (Ball::new(), Some(new_value)));
- }
- }
- }
- &SystemClauseType::TermAttributedVariables => {
- if self.machine_st.registers[1].is_constant() {
- self.machine_st.unify_atom(atom!("[]"), self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2])));
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
+ let output = printer.print();
- let seen_vars = self.machine_st.attr_vars_of_term(self.machine_st.registers[1]);
- let outcome = heap_loc_as_cell!(
- iter_to_heap_list(&mut self.machine_st.heap, seen_vars.into_iter())
+ match write!(&mut stream, "{}", output.result()) {
+ Ok(_) => {}
+ Err(_) => {
+ let stub = functor_stub(atom!("open"), 4);
+ let err = self.machine_st.existence_error(
+ ExistenceError::Stream(self.machine_st.registers[1]),
);
- unify_fn!(self.machine_st, self.machine_st.registers[2], outcome);
+ return Err(self.machine_st.error_form(err, stub));
}
- &SystemClauseType::Succeed => {}
- &SystemClauseType::TermVariables => {
- let a1 = self.machine_st.registers[1];
- let a2 = self.machine_st.registers[2];
+ }
- let stored_v = self.machine_st.store(self.machine_st.deref(a1));
+ stream.flush().unwrap();
+ Ok(())
+ }
- if stored_v.is_constant() {
- self.machine_st.unify_atom(atom!("[]"), self.machine_st.store(self.machine_st.deref(a2)));
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
+ #[inline(always)]
+ pub(crate) fn write_term_to_chars(&mut self) -> CallResult {
+ let printer = match self.machine_st.write_term(&self.indices.op_dir)? {
+ None => {
+ // this next line is executed by
+ // MachineState::write_term in this case. it's
+ // commented here because rustc can't prove
+ // that it's no longer borrowed.
- let mut seen_set = IndexSet::new();
+ // self.machine_st.fail = true;
+ return Ok(());
+ }
+ Some(printer) => printer,
+ };
- {
- let mut iter = stackless_preorder_iter(&mut self.machine_st.heap, stored_v);
+ let result = printer.print().result();
+ let chars = put_complete_string(&mut self.machine_st.heap, &result, &mut self.machine_st.atom_tbl);
- while let Some(addr) = iter.next() {
- let addr = unmark_cell_bits!(addr);
+ let result_addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- if addr.is_var() {
- seen_set.insert(addr);
- }
- }
- }
+ if let Some(var) = result_addr.as_var() {
+ self.machine_st.bind(var, chars);
+ } else {
+ unreachable!()
+ }
- let outcome = heap_loc_as_cell!(
- filtered_iter_to_heap_list(
- &mut self.machine_st.heap,
- seen_set.into_iter().rev(),
- |heap, value| {
- heap_bound_store(
- heap,
- heap_bound_deref(heap, value),
- ).is_var()
- },
- )
- );
+ Ok(())
+ }
- unify_fn!(self.machine_st, a2, outcome);
- }
- &SystemClauseType::TermVariablesUnderMaxDepth => {
- // Term, MaxDepth, VarList
- let max_depth = cell_as_fixnum!(
- self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]))
- ).get_num() as usize;
+ #[inline(always)]
+ pub(crate) fn scryer_prolog_version(&mut self) {
+ use git_version::git_version;
- self.machine_st.term_variables_under_max_depth(
- self.machine_st.registers[1],
- max_depth,
- self.machine_st.registers[3],
- );
- }
- &SystemClauseType::TruncateLiftedHeapTo => {
- let a1 = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let lh_offset = cell_as_fixnum!(a1).get_num() as usize;
+ let buffer = git_version!(cargo_prefix = "cargo:", fallback = "unknown");
+ let buffer_atom = self.machine_st.atom_tbl.build_with(buffer);
- self.machine_st.lifted_heap.truncate(lh_offset);
- }
- &SystemClauseType::UnifyWithOccursCheck => {
- let a1 = self.machine_st.registers[1];
- let a2 = self.machine_st.registers[2];
+ self.machine_st.unify_complete_string(
+ buffer_atom,
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])),
+ );
+ }
- unify_with_occurs_check!(&mut self.machine_st, a1, a2);
+ #[inline(always)]
+ pub(crate) fn crypto_random_byte(&mut self) {
+ let arg = self.machine_st.registers[1];
+ let mut bytes: [u8; 1] = [0];
+
+ match rng().fill(&mut bytes) {
+ Ok(()) => {}
+ Err(_) => {
+ // the error payload here is of type 'Unspecified',
+ // which contains no information whatsoever. So, for now,
+ // just fail.
+ self.machine_st.fail = true;
+ return;
}
- &SystemClauseType::UnwindEnvironments => {
- let mut e = self.machine_st.e;
- let mut cp = self.machine_st.cp;
+ }
- while e > 0 {
- if self.is_reset_cont_marker(cp) {
- self.machine_st.e = e;
- self.machine_st.p = CodePtr::Local(cp + 1); // skip the reset marker.
+ let byte = Fixnum::build_with(bytes[0] as i64);
+ self.machine_st.unify_fixnum(byte, arg);
+ }
- return Ok(());
- }
+ #[inline(always)]
+ pub(crate) fn crypto_data_hash(&mut self) {
+ let encoding = cell_as_atom!(self.machine_st.registers[2]);
+ let bytes = self.string_encoding_bytes(self.machine_st.registers[1], encoding);
- let and_frame = self.machine_st.stack.index_and_frame(e);
+ let algorithm = cell_as_atom!(self.machine_st.registers[4]);
- cp = and_frame.prelude.cp;
- e = and_frame.prelude.e;
- }
+ let ints_list = match algorithm {
+ atom!("sha3_224") => {
+ let mut context = Sha3_224::new();
+ context.input(&bytes);
+
+ heap_loc_as_cell!(
+ iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context
+ .result()
+ .as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ )
}
- &SystemClauseType::UnwindStack => {
- self.machine_st.unwind_stack();
+ atom!("sha3_256") => {
+ let mut context = Sha3_256::new();
+ context.input(&bytes);
+ heap_loc_as_cell!(
+ iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context
+ .result()
+ .as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ )
}
- &SystemClauseType::WAMInstructions => {
- let module_name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(
- self.machine_st.registers[1])
- ));
-
- let name = self.machine_st.registers[2];
- let arity = self.machine_st.registers[3];
-
- let name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(name)));
- let arity = self.machine_st.store(self.machine_st.deref(arity));
-
- let arity = match Number::try_from(arity) {
- Ok(Number::Fixnum(n)) => n.get_num() as usize,
- Ok(Number::Integer(n)) => n.to_usize().unwrap(),
- _ => {
- unreachable!()
- }
- };
-
- let key = (name, arity);
-
- let first_idx = match module_name {
- atom!("user") => self.indices.code_dir.get(&key),
- _ => match self.indices.modules.get(&module_name) {
- Some(module) => module.code_dir.get(&key),
- None => {
- let stub = functor_stub(key.0, key.1);
- let err = self.machine_st.session_error(
- SessionError::from(CompilationError::InvalidModuleResolution(
- module_name,
- )),
- );
+ atom!("sha3_384") => {
+ let mut context = Sha3_384::new();
+ context.input(&bytes);
- return Err(self.machine_st.error_form(err, stub));
- }
- },
- };
-
- let first_idx = match first_idx {
- Some(ref idx) if idx.local().is_some() => {
- if let Some(idx) = idx.local() {
- idx
- } else {
- unreachable!()
- }
- }
- _ => {
- let stub = functor_stub(name, arity);
- let err = self.machine_st.existence_error(
- ExistenceError::Procedure(name, arity),
- );
-
- return Err(self.machine_st.error_form(err, stub));
- }
- };
-
- let mut h = self.machine_st.heap.len();
+ heap_loc_as_cell!(
+ iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context
+ .result()
+ .as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ )
+ }
+ atom!("sha3_512") => {
+ let mut context = Sha3_512::new();
+ context.input(&bytes);
- let mut functors = vec![];
- let mut functor_list = vec![];
+ heap_loc_as_cell!(
+ iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context
+ .result()
+ .as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ )
+ }
+ atom!("blake2s256") => {
+ let mut context = Blake2s::new();
+ context.input(&bytes);
- walk_code(&self.code_repo.code, first_idx, |instr| {
- let old_len = functors.len();
- instr.enqueue_functors(h, &mut self.machine_st.arena, &mut functors);
- let new_len = functors.len();
+ heap_loc_as_cell!(
+ iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context
+ .result()
+ .as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ )
+ }
+ atom!("blake2b512") => {
+ let mut context = Blake2b::new();
+ context.input(&bytes);
- for index in old_len..new_len {
- let functor_len = functors[index].len();
+ heap_loc_as_cell!(
+ iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context
+ .result()
+ .as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ )
+ }
+ atom!("ripemd160") => {
+ let mut context = Ripemd160::new();
+ context.input(&bytes);
- match functor_len {
- 0 => {}
- 1 => {
- functor_list.push(heap_loc_as_cell!(h));
- h += functor_len;
- }
- _ => {
- functor_list.push(str_loc_as_cell!(h));
- h += functor_len;
- }
+ heap_loc_as_cell!(
+ iter_to_heap_list(
+ &mut self.machine_st.heap,
+ context
+ .result()
+ .as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ )
+ }
+ _ => {
+ let ints = digest::digest(
+ match algorithm {
+ atom!("sha256") => &digest::SHA256,
+ atom!("sha384") => &digest::SHA384,
+ atom!("sha512") => &digest::SHA512,
+ atom!("sha512_256") => &digest::SHA512_256,
+ _ => {
+ unreachable!()
}
- }
- });
-
- for functor in functors {
- self.machine_st.heap.extend(functor.into_iter());
- }
-
- let listing = heap_loc_as_cell!(
- iter_to_heap_list(&mut self.machine_st.heap, functor_list.into_iter())
+ },
+ &bytes,
);
- let listing_var = self.machine_st.registers[4];
-
- unify!(self.machine_st, listing, listing_var);
+ heap_loc_as_cell!(
+ iter_to_heap_list(
+ &mut self.machine_st.heap,
+ ints.as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ )
}
- &SystemClauseType::WriteTerm => {
- let mut stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("write_term"),
- 3,
- )?;
-
- self.machine_st.check_stream_properties(
- stream,
- StreamType::Text,
- None, // input
- atom!("write_term"),
- 3,
- )?;
+ };
- let opt_err = if !stream.is_output_stream() {
- Some(atom!("stream")) // 8.14.2.3 g)
- } else if stream.options().stream_type() == StreamType::Binary {
- Some(atom!("binary_stream")) // 8.14.2.3 h)
- } else {
- None
- };
+ unify!(self.machine_st, self.machine_st.registers[3], ints_list);
+ }
- if let Some(err_atom) = opt_err {
- return Err(self.machine_st.stream_permission_error(
- Permission::OutputStream,
- err_atom,
- stream,
- atom!("write_term"),
- 3,
- ));
- }
+ #[inline(always)]
+ pub(crate) fn crypto_data_hkdf(&mut self) {
+ let encoding = cell_as_atom!(self.machine_st.registers[2]);
+ let data = self.string_encoding_bytes(self.machine_st.registers[1], encoding);
- let printer = match self.machine_st.write_term(&self.indices.op_dir)? {
- Some(printer) => printer,
- None => {
- // this next line is executed by
- // MachineState::write_term in this case. it's
- // commented here because rustc can't prove
- // that it's no longer borrowed.
+ let stub1_gen = || functor_stub(atom!("crypto_data_hkdf"), 4);
+ let salt = self.machine_st.integers_to_bytevec(self.machine_st.registers[3], stub1_gen);
- // self.machine_st.fail = true;
- return Ok(());
- }
- };
+ let stub2_gen = || functor_stub(atom!("crypto_data_hkdf"), 4);
+ let info = self.machine_st.integers_to_bytevec(self.machine_st.registers[4], stub2_gen);
- let output = printer.print();
+ let algorithm = cell_as_atom!(self.machine_st.registers[5]);
- match write!(&mut stream, "{}", output.result()) {
- Ok(_) => {}
- Err(_) => {
- let stub = functor_stub(atom!("open"), 4);
- let err = self.machine_st.existence_error(
- ExistenceError::Stream(self.machine_st.registers[1]),
- );
+ let length = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[6]));
- return Err(self.machine_st.error_form(err, stub));
- }
+ let length = match Number::try_from(length) {
+ Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).unwrap(),
+ Ok(Number::Integer(n)) => match n.to_usize() {
+ Some(u) => u,
+ _ => {
+ self.machine_st.fail = true;
+ return;
}
-
- stream.flush().unwrap();
+ },
+ _ => {
+ unreachable!()
}
- &SystemClauseType::WriteTermToChars => {
- let printer = match self.machine_st.write_term(&self.indices.op_dir)? {
- None => {
- // this next line is executed by
- // MachineState::write_term in this case. it's
- // commented here because rustc can't prove
- // that it's no longer borrowed.
-
- // self.machine_st.fail = true;
- return Ok(());
- }
- Some(printer) => printer,
- };
-
- let result = printer.print().result();
- let chars = put_complete_string(&mut self.machine_st.heap, &result, &mut self.machine_st.atom_tbl);
-
- let result_addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ };
- if let Some(var) = result_addr.as_var() {
- self.machine_st.bind(var, chars);
- } else {
- unreachable!()
+ let ints_list = {
+ let digest_alg = match algorithm {
+ atom!("sha256") => hkdf::HKDF_SHA256,
+ atom!("sha384") => hkdf::HKDF_SHA384,
+ atom!("sha512") => hkdf::HKDF_SHA512,
+ _ => {
+ self.machine_st.fail = true;
+ return;
}
- }
- &SystemClauseType::ScryerPrologVersion => {
- use git_version::git_version;
+ };
- let buffer = git_version!(cargo_prefix = "cargo:", fallback = "unknown");
- let buffer_atom = self.machine_st.atom_tbl.build_with(buffer);
+ let salt = hkdf::Salt::new(digest_alg, &salt);
+ let mut bytes: Vec<u8> = Vec::new();
- self.machine_st.unify_complete_string(buffer_atom, self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])));
- }
- &SystemClauseType::CryptoRandomByte => {
- let arg = self.machine_st.registers[1];
- let mut bytes: [u8; 1] = [0];
+ bytes.resize(length, 0);
- match rng().fill(&mut bytes) {
- Ok(()) => {}
- Err(_) => {
- // the error payload here is of type 'Unspecified',
- // which contains no information whatsoever. So, for now,
- // just fail.
- self.machine_st.fail = true;
- return Ok(());
- }
+ match salt.extract(&data).expand(&[&info[..]], MyKey(length)) {
+ Ok(r) => {
+ r.fill(&mut bytes).unwrap();
+ }
+ _ => {
+ self.machine_st.fail = true;
+ return;
}
-
- let byte = Fixnum::build_with(bytes[0] as i64);
- self.machine_st.unify_fixnum(byte, arg);
}
- &SystemClauseType::CryptoDataHash => {
- let encoding = cell_as_atom!(self.machine_st.registers[2]);
- let bytes = self.string_encoding_bytes(self.machine_st.registers[1], encoding);
- let algorithm = cell_as_atom!(self.machine_st.registers[4]);
-
- let ints_list = match algorithm {
- atom!("sha3_224") => {
- let mut context = Sha3_224::new();
- context.input(&bytes);
+ heap_loc_as_cell!(
+ iter_to_heap_list(
+ &mut self.machine_st.heap,
+ bytes
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ )
+ };
- heap_loc_as_cell!(
- iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .result()
- .as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- )
- )
- }
- atom!("sha3_256") => {
- let mut context = Sha3_256::new();
- context.input(&bytes);
- heap_loc_as_cell!(
- iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .result()
- .as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- )
- )
- }
- atom!("sha3_384") => {
- let mut context = Sha3_384::new();
- context.input(&bytes);
-
- heap_loc_as_cell!(
- iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .result()
- .as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- )
- )
- }
- atom!("sha3_512") => {
- let mut context = Sha3_512::new();
- context.input(&bytes);
-
- heap_loc_as_cell!(
- iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .result()
- .as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- )
- )
- }
- atom!("blake2s256") => {
- let mut context = Blake2s::new();
- context.input(&bytes);
-
- heap_loc_as_cell!(
- iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .result()
- .as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- )
- )
- }
- atom!("blake2b512") => {
- let mut context = Blake2b::new();
- context.input(&bytes);
-
- heap_loc_as_cell!(
- iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .result()
- .as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- )
- )
- }
- atom!("ripemd160") => {
- let mut context = Ripemd160::new();
- context.input(&bytes);
-
- heap_loc_as_cell!(
- iter_to_heap_list(
- &mut self.machine_st.heap,
- context
- .result()
- .as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- )
- )
- }
- _ => {
- let ints = digest::digest(
- match algorithm {
- atom!("sha256") => &digest::SHA256,
- atom!("sha384") => &digest::SHA384,
- atom!("sha512") => &digest::SHA512,
- atom!("sha512_256") => &digest::SHA512_256,
- _ => {
- unreachable!()
- }
- },
- &bytes,
- );
-
- heap_loc_as_cell!(
- iter_to_heap_list(
- &mut self.machine_st.heap,
- ints.as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- )
- )
- }
- };
+ unify!(self.machine_st, self.machine_st.registers[7], ints_list);
+ }
- unify!(self.machine_st, self.machine_st.registers[3], ints_list);
+ #[inline(always)]
+ pub(crate) fn crypto_password_hash(&mut self) {
+ let stub1_gen = || functor_stub(atom!("crypto_password_hash"), 3);
+ let data = self.machine_st.integers_to_bytevec(self.machine_st.registers[1], stub1_gen);
+ let stub2_gen = || functor_stub(atom!("crypto_password_hash"), 3);
+ let salt = self.machine_st.integers_to_bytevec(self.machine_st.registers[2], stub2_gen);
+
+ let iterations = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3]));
+
+ let iterations = match Number::try_from(iterations) {
+ Ok(Number::Fixnum(n)) => u64::try_from(n.get_num()).unwrap(),
+ Ok(Number::Integer(n)) => match n.to_u64() {
+ Some(i) => i,
+ None => {
+ self.machine_st.fail = true;
+ return;
+ }
+ },
+ _ => {
+ unreachable!()
}
- &SystemClauseType::CryptoDataHKDF => {
- let encoding = cell_as_atom!(self.machine_st.registers[2]);
- let data = self.string_encoding_bytes(self.machine_st.registers[1], encoding);
+ };
- let stub1_gen = || functor_stub(atom!("crypto_data_hkdf"), 4);
- let salt = self.machine_st.integers_to_bytevec(self.machine_st.registers[3], stub1_gen);
+ let ints_list = {
+ let mut bytes = [0u8; digest::SHA512_OUTPUT_LEN];
- let stub2_gen = || functor_stub(atom!("crypto_data_hkdf"), 4);
- let info = self.machine_st.integers_to_bytevec(self.machine_st.registers[4], stub2_gen);
+ pbkdf2::derive(
+ pbkdf2::PBKDF2_HMAC_SHA512,
+ NonZeroU32::new(iterations as u32).unwrap(),
+ &salt,
+ &data,
+ &mut bytes,
+ );
- let algorithm = cell_as_atom!(self.machine_st.registers[5]);
+ heap_loc_as_cell!(
+ iter_to_heap_list(
+ &mut self.machine_st.heap,
+ bytes
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ )
+ };
- let length = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[6]));
+ unify!(self.machine_st, self.machine_st.registers[4], ints_list);
+ }
- let length = match Number::try_from(length) {
- Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).unwrap(),
- Ok(Number::Integer(n)) => match n.to_usize() {
- Some(u) => u,
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- },
- _ => {
- unreachable!()
- }
- };
+ #[inline(always)]
+ pub(crate) fn crypto_data_encrypt(&mut self) {
+ let encoding = cell_as_atom!(self.machine_st.registers[3]);
- let ints_list = {
- let digest_alg = match algorithm {
- atom!("sha256") => hkdf::HKDF_SHA256,
- atom!("sha384") => hkdf::HKDF_SHA384,
- atom!("sha512") => hkdf::HKDF_SHA512,
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- };
+ let data = self.string_encoding_bytes(self.machine_st.registers[1], encoding);
+ let aad = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
- let salt = hkdf::Salt::new(digest_alg, &salt);
- let mut bytes: Vec<u8> = Vec::new();
+ let stub2_gen = || functor_stub(atom!("crypto_data_encrypt"), 7);
+ let key = self.machine_st.integers_to_bytevec(self.machine_st.registers[4], stub2_gen);
- bytes.resize(length, 0);
+ let stub3_gen = || functor_stub(atom!("crypto_data_encrypt"), 7);
+ let iv = self.machine_st.integers_to_bytevec(self.machine_st.registers[5], stub3_gen);
- match salt.extract(&data).expand(&[&info[..]], MyKey(length)) {
- Ok(r) => {
- r.fill(&mut bytes).unwrap();
- }
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
+ let unbound_key = aead::UnboundKey::new(&aead::CHACHA20_POLY1305, &key).unwrap();
+ let nonce = aead::Nonce::try_assume_unique_for_key(&iv).unwrap();
+ let key = aead::LessSafeKey::new(unbound_key);
- heap_loc_as_cell!(
- iter_to_heap_list(
- &mut self.machine_st.heap,
- bytes
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- )
- )
- };
+ let mut in_out = data;
- unify!(self.machine_st, self.machine_st.registers[7], ints_list);
+ let tag = match key.seal_in_place_separate_tag(
+ nonce,
+ aead::Aad::from(aad),
+ &mut in_out,
+ ) {
+ Ok(d) => d,
+ _ => {
+ self.machine_st.fail = true;
+ return;
}
- &SystemClauseType::CryptoPasswordHash => {
- let stub1_gen = || functor_stub(atom!("crypto_password_hash"), 3);
- let data = self.machine_st.integers_to_bytevec(self.machine_st.registers[1], stub1_gen);
- let stub2_gen = || functor_stub(atom!("crypto_password_hash"), 3);
- let salt = self.machine_st.integers_to_bytevec(self.machine_st.registers[2], stub2_gen);
-
- let iterations = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[3]));
-
- let iterations = match Number::try_from(iterations) {
- Ok(Number::Fixnum(n)) => u64::try_from(n.get_num()).unwrap(),
- Ok(Number::Integer(n)) => match n.to_u64() {
- Some(i) => i,
- None => {
- self.machine_st.fail = true;
- return Ok(());
- }
- },
- _ => {
- unreachable!()
- }
- };
-
- let ints_list = {
- let mut bytes = [0u8; digest::SHA512_OUTPUT_LEN];
+ };
- pbkdf2::derive(
- pbkdf2::PBKDF2_HMAC_SHA512,
- NonZeroU32::new(iterations as u32).unwrap(),
- &salt,
- &data,
- &mut bytes,
- );
+ let tag_list = heap_loc_as_cell!(
+ iter_to_heap_list(
+ &mut self.machine_st.heap,
+ tag.as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ );
- heap_loc_as_cell!(
- iter_to_heap_list(
- &mut self.machine_st.heap,
- bytes
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- )
- )
- };
+ let complete_string = {
+ let buffer = String::from_iter(in_out.iter().map(|b| *b as char));
+ put_complete_string(&mut self.machine_st.heap, &buffer, &mut self.machine_st.atom_tbl)
+ };
- unify!(self.machine_st, self.machine_st.registers[4], ints_list);
- }
- &SystemClauseType::CryptoDataEncrypt => {
- let encoding = cell_as_atom!(self.machine_st.registers[3]);
+ unify!(self.machine_st, self.machine_st.registers[6], tag_list);
+ unify!(self.machine_st, self.machine_st.registers[7], complete_string);
+ }
- let data = self.string_encoding_bytes(self.machine_st.registers[1], encoding);
- let aad = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
+ #[inline(always)]
+ pub(crate) fn crypto_data_decrypt(&mut self) {
+ let data = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
+ let encoding = cell_as_atom!(self.machine_st.registers[5]);
- let stub2_gen = || functor_stub(atom!("crypto_data_encrypt"), 7);
- let key = self.machine_st.integers_to_bytevec(self.machine_st.registers[4], stub2_gen);
+ let aad = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
+ let stub1_gen = || functor_stub(atom!("crypto_data_decrypt"), 7);
- let stub3_gen = || functor_stub(atom!("crypto_data_encrypt"), 7);
- let iv = self.machine_st.integers_to_bytevec(self.machine_st.registers[5], stub3_gen);
+ let key = self.machine_st.integers_to_bytevec(self.machine_st.registers[3], stub1_gen);
+ let stub2_gen = || functor_stub(atom!("crypto_data_decrypt"), 7);
+ let iv = self.machine_st.integers_to_bytevec(self.machine_st.registers[4], stub2_gen);
- let unbound_key = aead::UnboundKey::new(&aead::CHACHA20_POLY1305, &key).unwrap();
- let nonce = aead::Nonce::try_assume_unique_for_key(&iv).unwrap();
- let key = aead::LessSafeKey::new(unbound_key);
+ let unbound_key = aead::UnboundKey::new(&aead::CHACHA20_POLY1305, &key).unwrap();
+ let nonce = aead::Nonce::try_assume_unique_for_key(&iv).unwrap();
+ let key = aead::LessSafeKey::new(unbound_key);
- let mut in_out = data;
+ let mut in_out = data;
- let tag = match key.seal_in_place_separate_tag(
- nonce,
- aead::Aad::from(aad),
- &mut in_out,
- ) {
+ let complete_string = {
+ let decrypted_data =
+ match key.open_in_place(nonce, aead::Aad::from(aad), &mut in_out) {
Ok(d) => d,
_ => {
self.machine_st.fail = true;
- return Ok(());
+ return;
}
};
- let tag_list = heap_loc_as_cell!(
- iter_to_heap_list(
- &mut self.machine_st.heap,
- tag.as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- )
- );
-
- let complete_string = {
- let buffer = String::from_iter(in_out.iter().map(|b| *b as char));
- put_complete_string(&mut self.machine_st.heap, &buffer, &mut self.machine_st.atom_tbl)
- };
-
- unify!(self.machine_st, self.machine_st.registers[6], tag_list);
- unify!(self.machine_st, self.machine_st.registers[7], complete_string);
- }
- &SystemClauseType::CryptoDataDecrypt => {
- let data = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
- let encoding = cell_as_atom!(self.machine_st.registers[5]);
-
- let aad = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
- let stub1_gen = || functor_stub(atom!("crypto_data_decrypt"), 7);
-
- let key = self.machine_st.integers_to_bytevec(self.machine_st.registers[3], stub1_gen);
- let stub2_gen = || functor_stub(atom!("crypto_data_decrypt"), 7);
- let iv = self.machine_st.integers_to_bytevec(self.machine_st.registers[4], stub2_gen);
+ let buffer = match encoding {
+ atom!("octet") => String::from_iter(decrypted_data.iter().map(|b| *b as char)),
+ atom!("utf8") => match String::from_utf8(decrypted_data.to_vec()) {
+ Ok(str) => str,
+ _ => {
+ self.machine_st.fail = true;
+ return;
+ }
+ },
+ _ => {
+ unreachable!()
+ }
+ };
- let unbound_key = aead::UnboundKey::new(&aead::CHACHA20_POLY1305, &key).unwrap();
- let nonce = aead::Nonce::try_assume_unique_for_key(&iv).unwrap();
- let key = aead::LessSafeKey::new(unbound_key);
+ put_complete_string(&mut self.machine_st.heap, &buffer, &mut self.machine_st.atom_tbl)
+ };
- let mut in_out = data;
+ unify!(self.machine_st, self.machine_st.registers[6], complete_string);
+ }
- let complete_string = {
- let decrypted_data =
- match key.open_in_place(nonce, aead::Aad::from(aad), &mut in_out) {
- Ok(d) => d,
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- };
+ #[inline(always)]
+ pub(crate) fn crypto_curve_scalar_mult(&mut self) {
+ let curve = cell_as_atom!(self.machine_st.registers[1]);
- let buffer = match encoding {
- atom!("octet") => String::from_iter(decrypted_data.iter().map(|b| *b as char)),
- atom!("utf8") => match String::from_utf8(decrypted_data.to_vec()) {
- Ok(str) => str,
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- },
- _ => {
- unreachable!()
- }
- };
+ let curve_id = match curve {
+ atom!("secp112r1") => Nid::SECP112R1,
+ atom!("secp256k1") => Nid::SECP256K1,
+ _ => {
+ unreachable!()
+ }
+ };
- put_complete_string(&mut self.machine_st.heap, &buffer, &mut self.machine_st.atom_tbl)
- };
+ let scalar = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
- unify!(self.machine_st, self.machine_st.registers[6], complete_string);
+ let scalar = match Number::try_from(scalar) {
+ Ok(Number::Fixnum(n)) => Integer::from(n.get_num()),
+ Ok(Number::Integer(n)) => Integer::from(&*n),
+ _ => {
+ unreachable!()
}
- &SystemClauseType::CryptoCurveScalarMult => {
- let curve = cell_as_atom!(self.machine_st.registers[1]);
+ };
- let curve_id = match curve {
- atom!("secp112r1") => Nid::SECP112R1,
- atom!("secp256k1") => Nid::SECP256K1,
- _ => {
- unreachable!()
- }
- };
+ let stub_gen = || functor_stub(atom!("crypto_curve_scalar_mult"), 5);
+ let qbytes = self.machine_st.integers_to_bytevec(self.machine_st.registers[3], stub_gen);
- let scalar = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[2]));
+ let mut bnctx = BigNumContext::new().unwrap();
+ let group = EcGroup::from_curve_name(curve_id).unwrap();
+ let mut point = EcPoint::from_bytes(&group, &qbytes, &mut bnctx).unwrap();
+ let scalar_bn = BigNum::from_dec_str(&scalar.to_string()).unwrap();
+ let mut result = EcPoint::new(&group).unwrap();
- let scalar = match Number::try_from(scalar) {
- Ok(Number::Fixnum(n)) => Integer::from(n.get_num()),
- Ok(Number::Integer(n)) => Integer::from(&*n),
- _ => {
- unreachable!()
- }
- };
+ result.mul(&group, &mut point, &scalar_bn, &mut bnctx).ok();
- let stub_gen = || functor_stub(atom!("crypto_curve_scalar_mult"), 5);
- let qbytes = self.machine_st.integers_to_bytevec(self.machine_st.registers[3], stub_gen);
+ let mut rx = BigNum::new().unwrap();
+ let mut ry = BigNum::new().unwrap();
- let mut bnctx = BigNumContext::new().unwrap();
- let group = EcGroup::from_curve_name(curve_id).unwrap();
- let mut point = EcPoint::from_bytes(&group, &qbytes, &mut bnctx).unwrap();
- let scalar_bn = BigNum::from_dec_str(&scalar.to_string()).unwrap();
- let mut result = EcPoint::new(&group).unwrap();
+ result
+ .affine_coordinates_gfp(&group, &mut rx, &mut ry, &mut bnctx)
+ .ok();
- result.mul(&group, &mut point, &scalar_bn, &mut bnctx).ok();
+ let sx = put_complete_string(
+ &mut self.machine_st.heap,
+ &rx.to_dec_str().unwrap(),
+ &mut self.machine_st.atom_tbl,
+ );
- let mut rx = BigNum::new().unwrap();
- let mut ry = BigNum::new().unwrap();
+ let sy = put_complete_string(
+ &mut self.machine_st.heap,
+ &ry.to_dec_str().unwrap(),
+ &mut self.machine_st.atom_tbl,
+ );
- result
- .affine_coordinates_gfp(&group, &mut rx, &mut ry, &mut bnctx)
- .ok();
+ unify!(self.machine_st, self.machine_st.registers[4], sx);
+ unify!(self.machine_st, self.machine_st.registers[5], sy);
+ }
- let sx = put_complete_string(
- &mut self.machine_st.heap,
- &rx.to_dec_str().unwrap(),
- &mut self.machine_st.atom_tbl,
- );
+ #[inline(always)]
+ pub(crate) fn ed25519_new_key_pair(&mut self) {
+ let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(rng()).unwrap();
+ let complete_string = {
+ let buffer = String::from_iter(pkcs8_bytes.as_ref().iter().map(|b| *b as char));
+ put_complete_string(
+ &mut self.machine_st.heap,
+ &buffer,
+ &mut self.machine_st.atom_tbl,
+ )
+ };
- let sy = put_complete_string(
- &mut self.machine_st.heap,
- &ry.to_dec_str().unwrap(),
- &mut self.machine_st.atom_tbl,
- );
+ unify!(self.machine_st, self.machine_st.registers[1], complete_string)
+ }
- unify!(self.machine_st, self.machine_st.registers[4], sx);
- unify!(self.machine_st, self.machine_st.registers[5], sy);
- }
- &SystemClauseType::Ed25519NewKeyPair => {
- let pkcs8_bytes = signature::Ed25519KeyPair::generate_pkcs8(rng()).unwrap();
- let complete_string = {
- let buffer = String::from_iter(pkcs8_bytes.as_ref().iter().map(|b| *b as char));
- put_complete_string(
- &mut self.machine_st.heap,
- &buffer,
- &mut self.machine_st.atom_tbl,
- )
- };
+ #[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"));
- unify!(self.machine_st, self.machine_st.registers[1], complete_string)
+ let key_pair = match signature::Ed25519KeyPair::from_pkcs8(&bytes) {
+ Ok(kp) => kp,
+ _ => {
+ self.machine_st.fail = true;
+ return;
}
- &SystemClauseType::Ed25519KeyPairPublicKey => {
- 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 Ok(());
- }
- };
+ let complete_string = {
+ let buffer = String::from_iter(
+ key_pair.public_key().as_ref().iter().map(|b| *b as char),
+ );
+
+ put_complete_string(
+ &mut self.machine_st.heap,
+ &buffer,
+ &mut self.machine_st.atom_tbl,
+ )
+ };
- let complete_string = {
- let buffer = String::from_iter(
- key_pair.public_key().as_ref().iter().map(|b| *b as char),
- );
+ unify!(self.machine_st, self.machine_st.registers[2], complete_string);
+ }
- put_complete_string(
- &mut self.machine_st.heap,
- &buffer,
- &mut self.machine_st.atom_tbl,
- )
- };
+ #[inline(always)]
+ pub(crate) fn ed25519_sign(&mut self) {
+ let key = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
+ let encoding = cell_as_atom!(self.machine_st.registers[3]);
+ let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
- unify!(self.machine_st, self.machine_st.registers[2], complete_string);
+ let key_pair = match signature::Ed25519KeyPair::from_pkcs8(&key) {
+ Ok(kp) => kp,
+ _ => {
+ self.machine_st.fail = true;
+ return;
}
- &SystemClauseType::Ed25519Sign => {
- let key = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
- let encoding = cell_as_atom!(self.machine_st.registers[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 Ok(());
- }
- };
+ let sig = key_pair.sign(&data);
- let sig = key_pair.sign(&data);
+ let sig_list = heap_loc_as_cell!(
+ iter_to_heap_list(
+ &mut self.machine_st.heap,
+ sig.as_ref()
+ .iter()
+ .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
+ )
+ );
- let sig_list = heap_loc_as_cell!(
- iter_to_heap_list(
- &mut self.machine_st.heap,
- sig.as_ref()
- .iter()
- .map(|b| fixnum_as_cell!(Fixnum::build_with(*b as i64))),
- )
- );
+ unify!(self.machine_st, self.machine_st.registers[4], sig_list);
+ }
- unify!(self.machine_st, self.machine_st.registers[4], sig_list);
- }
- &SystemClauseType::Ed25519Verify => {
- let key = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
- let encoding = cell_as_atom!(self.machine_st.registers[3]);
- let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
- let stub_gen = || functor_stub(atom!("ed25519_verify"), 5);
- let signature = self.machine_st.integers_to_bytevec(self.machine_st.registers[4], stub_gen);
+ #[inline(always)]
+ pub(crate) fn ed25519_verify(&mut self) {
+ let key = self.string_encoding_bytes(self.machine_st.registers[1], atom!("octet"));
+ let encoding = cell_as_atom!(self.machine_st.registers[3]);
+ let data = self.string_encoding_bytes(self.machine_st.registers[2], encoding);
+ let stub_gen = || functor_stub(atom!("ed25519_verify"), 5);
+ 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);
+ let peer_public_key = signature::UnparsedPublicKey::new(&signature::ED25519, &key);
- match peer_public_key.verify(&data, &signature) {
- Ok(_) => {}
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
+ match peer_public_key.verify(&data, &signature) {
+ Ok(_) => {}
+ _ => {
+ self.machine_st.fail = true;
}
- &SystemClauseType::Curve25519ScalarMult => {
- let stub1_gen = || functor_stub(atom!("curve25519_scalar_mult"), 3);
- let scalar_bytes = self.machine_st.integers_to_bytevec(self.machine_st.registers[1], stub1_gen);
- let scalar = Scalar(<[u8; 32]>::try_from(&scalar_bytes[..]).unwrap());
+ }
+ }
- let stub2_gen = || functor_stub(atom!("curve25519_scalar_mult"), 3);
- let point_bytes = self.machine_st.integers_to_bytevec(self.machine_st.registers[2], stub2_gen);
- let point = GroupElement(<[u8; 32]>::try_from(&point_bytes[..]).unwrap());
+ #[inline(always)]
+ pub(crate) fn curve25519_scalar_mult(&mut self) {
+ let stub1_gen = || functor_stub(atom!("curve25519_scalar_mult"), 3);
+ let scalar_bytes = self.machine_st.integers_to_bytevec(self.machine_st.registers[1], stub1_gen);
+ let scalar = Scalar(<[u8; 32]>::try_from(&scalar_bytes[..]).unwrap());
- let result = scalarmult(&scalar, &point).unwrap();
+ let stub2_gen = || functor_stub(atom!("curve25519_scalar_mult"), 3);
+ let point_bytes = self.machine_st.integers_to_bytevec(self.machine_st.registers[2], stub2_gen);
+ let point = GroupElement(<[u8; 32]>::try_from(&point_bytes[..]).unwrap());
- let string = String::from_iter(result[..].iter().map(|b| *b as char));
- let cstr = put_complete_string(&mut self.machine_st.heap, &string, &mut self.machine_st.atom_tbl);
+ let result = scalarmult(&scalar, &point).unwrap();
- unify!(self.machine_st, self.machine_st.registers[3], cstr);
- }
- &SystemClauseType::FirstNonOctet => {
- let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let string = String::from_iter(result[..].iter().map(|b| *b as char));
+ let cstr = put_complete_string(&mut self.machine_st.heap, &string, &mut self.machine_st.atom_tbl);
- if let Some(string) = self.machine_st.value_to_str_like(addr) {
- for c in string.as_str().chars() {
- if c as u32 > 255 {
- let non_octet = self.machine_st.atom_tbl.build_with(&c.to_string());
- self.machine_st.unify_atom(non_octet, self.machine_st.registers[2]);
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- }
- }
+ unify!(self.machine_st, self.machine_st.registers[3], cstr);
+ }
- self.machine_st.fail = true;
- return Ok(());
+ #[inline(always)]
+ pub(crate) fn first_non_octet(&mut self) {
+ let addr = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+
+ if let Some(string) = self.machine_st.value_to_str_like(addr) {
+ for c in string.as_str().chars() {
+ if c as u32 > 255 {
+ let non_octet = self.machine_st.atom_tbl.build_with(&c.to_string());
+ self.machine_st.unify_atom(non_octet, self.machine_st.registers[2]);
+ return;
+ }
}
- &SystemClauseType::LoadHTML => {
- if let Some(string) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- let doc = select::document::Document::from_read(string.as_str().as_bytes()).unwrap();
- let result = self.html_node_to_term(doc.nth(0).unwrap());
+ }
+
+ self.machine_st.fail = true;
+ }
+
+ #[inline(always)]
+ pub(crate) fn load_html(&mut self) {
+ if let Some(string) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ let doc = select::document::Document::from_read(string.as_str().as_bytes()).unwrap();
+ let result = self.html_node_to_term(doc.nth(0).unwrap());
+
+ unify!(self.machine_st, self.machine_st.registers[2], result);
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+ #[inline(always)]
+ pub(crate) fn load_xml(&mut self) {
+ if let Some(string) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ match roxmltree::Document::parse(string.as_str()) {
+ Ok(doc) => {
+ let result = self.xml_node_to_term(doc.root_element());
unify!(self.machine_st, self.machine_st.registers[2], result);
- } else {
- self.machine_st.fail = true;
- return Ok(());
}
- }
- &SystemClauseType::LoadXML => {
- if let Some(string) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- match roxmltree::Document::parse(string.as_str()) {
- Ok(doc) => {
- let result = self.xml_node_to_term(doc.root_element());
- unify!(self.machine_st, self.machine_st.registers[2], result);
- }
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
- } else {
+ _ => {
self.machine_st.fail = true;
- return Ok(());
}
}
- &SystemClauseType::GetEnv => {
- if let Some(key) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
- match env::var(key.as_str()) {
- Ok(value) => {
- let cstr = put_complete_string(
- &mut self.machine_st.heap,
- &value,
- &mut self.machine_st.atom_tbl,
- );
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
- unify!(self.machine_st, self.machine_st.registers[2], cstr);
- }
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
- } else {
+ #[inline(always)]
+ pub(crate) fn get_env(&mut self) {
+ if let Some(key) = self.machine_st.value_to_str_like(self.machine_st.registers[1]) {
+ match env::var(key.as_str()) {
+ Ok(value) => {
+ let cstr = put_complete_string(
+ &mut self.machine_st.heap,
+ &value,
+ &mut self.machine_st.atom_tbl,
+ );
+
+ unify!(self.machine_st, self.machine_st.registers[2], cstr);
+ }
+ _ => {
self.machine_st.fail = true;
- return Ok(());
}
}
- &SystemClauseType::SetEnv => {
- let key = self.machine_st.value_to_str_like(self.machine_st.registers[1]).unwrap();
- let value = self.machine_st.value_to_str_like(self.machine_st.registers[2]).unwrap();
+ } else {
+ self.machine_st.fail = true;
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn set_env(&mut self) {
+ let key = self.machine_st.value_to_str_like(self.machine_st.registers[1]).unwrap();
+ let value = self.machine_st.value_to_str_like(self.machine_st.registers[2]).unwrap();
- env::set_var(key.as_str(), value.as_str());
+ env::set_var(key.as_str(), value.as_str());
+ }
+
+ #[inline(always)]
+ pub(crate) fn unset_env(&mut self) {
+ let key = self.machine_st.value_to_str_like(self.machine_st.registers[1]).unwrap();
+ env::remove_var(key.as_str());
+ }
+
+ #[inline(always)]
+ pub(crate) fn pid(&mut self) {
+ let pid = process::id();
+
+ match fixnum!(Number, pid as i64, &mut self.machine_st.arena) {
+ Number::Fixnum(pid) => {
+ self.machine_st.unify_fixnum(pid, self.machine_st.registers[1]);
}
- &SystemClauseType::UnsetEnv => {
- let key = self.machine_st.value_to_str_like(self.machine_st.registers[1]).unwrap();
- env::remove_var(key.as_str());
+ Number::Integer(pid) => {
+ self.machine_st.unify_big_int(pid, self.machine_st.registers[1]);
}
- &SystemClauseType::PID => {
- let pid = process::id();
-
- match fixnum!(Number, pid as i64, &mut self.machine_st.arena) {
- Number::Fixnum(pid) => {
- self.machine_st.unify_fixnum(pid, self.machine_st.registers[1]);
- }
- Number::Integer(pid) => {
- self.machine_st.unify_big_int(pid, self.machine_st.registers[1]);
- }
- _ => {
- unreachable!();
- }
- }
+ _ => {
+ unreachable!();
}
- &SystemClauseType::Shell => {
- // shell executes a command in a system shell
- // the code looks for a SHELL env var to do it in a UNIX-style
- // if not found, the code looks for COMSPEC env var to do it in a DOS-style
- // the output is printed directly to stdout
- // the output status code is returned after finishing
- fn command_result(machine: &mut MachineState, command: std::io::Result<process::ExitStatus>) {
- match command {
- Ok(status) => {
- match status.code() {
- Some(code) => {
- let code = integer_as_cell!(Number::arena_from(code, &mut machine.arena));
- unify!(machine, code, machine.registers[2]);
- }
- _ => {
- machine.fail = true;
- }
- }
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn shell(&mut self) {
+ // shell executes a command in a system shell
+ // the code looks for a SHELL env var to do it in a UNIX-style
+ // if not found, the code looks for COMSPEC env var to do it in a DOS-style
+ // the output is printed directly to stdout
+ // the output status code is returned after finishing
+ fn command_result(machine: &mut MachineState, command: std::io::Result<process::ExitStatus>) {
+ match command {
+ Ok(status) => {
+ match status.code() {
+ Some(code) => {
+ let code = integer_as_cell!(Number::arena_from(code, &mut machine.arena));
+ unify!(machine, code, machine.registers[2]);
}
_ => {
machine.fail = true;
}
}
}
+ _ => {
+ machine.fail = true;
+ }
+ }
+ }
- let command = self.machine_st.value_to_str_like(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))).unwrap();
+ let command = self.machine_st.value_to_str_like(
+ self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
+ ).unwrap();
- match env::var("SHELL") {
+ match env::var("SHELL") {
+ Ok(value) => {
+ let command = process::Command::new(&value)
+ .arg("-c")
+ .arg(command.as_str())
+ .status();
+ command_result(&mut self.machine_st, command);
+ }
+ _ => {
+ match env::var("COMSPEC") {
Ok(value) => {
let command = process::Command::new(&value)
- .arg("-c")
+ .arg("/C")
.arg(command.as_str())
.status();
command_result(&mut self.machine_st, command);
}
_ => {
- match env::var("COMSPEC") {
- Ok(value) => {
- let command = process::Command::new(&value)
- .arg("/C")
- .arg(command.as_str())
- .status();
- command_result(&mut self.machine_st, command);
- }
- _ => {
- self.machine_st.fail = true;
- }
- }
+ self.machine_st.fail = true;
}
- };
+ }
}
- &SystemClauseType::CharsBase64 => {
- let padding = cell_as_atom!(self.machine_st.registers[3]);
- let charset = cell_as_atom!(self.machine_st.registers[4]);
-
- let config = if padding == atom!("true") {
- if charset == atom!("standard") {
- base64::STANDARD
- } else {
- base64::URL_SAFE
- }
- } else {
- if charset == atom!("standard") {
- base64::STANDARD_NO_PAD
- } else {
- base64::URL_SAFE_NO_PAD
- }
- };
-
- if self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])).is_var() {
- let b64 = self.machine_st.value_to_str_like(self.machine_st.registers[2]).unwrap();
- let bytes = base64::decode_config(b64.as_str(), config);
-
- match bytes {
- Ok(bs) => {
- let string = String::from_iter(bs.iter().map(|b| *b as char));
- let cstr = put_complete_string(
- &mut self.machine_st.heap,
- &string,
- &mut self.machine_st.atom_tbl,
- );
+ };
+ }
- unify!(self.machine_st, self.machine_st.registers[1], cstr);
- }
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
- } else {
- let mut bytes = vec![];
- for c in self.machine_st.value_to_str_like(self.machine_st.registers[1]).unwrap().as_str().chars() {
- if c as u32 > 255 {
- let stub = functor_stub(atom!("chars_base64"), 3);
-
- let err = self.machine_st.type_error(
- ValidType::Byte,
- char_as_cell!(c),
- );
+ #[inline(always)]
+ pub(crate) fn chars_base64(&mut self) -> CallResult {
+ let padding = cell_as_atom!(self.machine_st.registers[3]);
+ let charset = cell_as_atom!(self.machine_st.registers[4]);
- return Err(self.machine_st.error_form(err, stub));
- }
+ let config = if padding == atom!("true") {
+ if charset == atom!("standard") {
+ base64::STANDARD
+ } else {
+ base64::URL_SAFE
+ }
+ } else {
+ if charset == atom!("standard") {
+ base64::STANDARD_NO_PAD
+ } else {
+ base64::URL_SAFE_NO_PAD
+ }
+ };
- bytes.push(c as u8);
- }
+ if self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])).is_var() {
+ let b64 = self.machine_st.value_to_str_like(self.machine_st.registers[2]).unwrap();
+ let bytes = base64::decode_config(b64.as_str(), config);
- let b64 = base64::encode_config(bytes, config);
+ match bytes {
+ Ok(bs) => {
+ let string = String::from_iter(bs.iter().map(|b| *b as char));
let cstr = put_complete_string(
&mut self.machine_st.heap,
- &b64,
+ &string,
&mut self.machine_st.atom_tbl,
);
- unify!(self.machine_st, self.machine_st.registers[2], cstr);
+ unify!(self.machine_st, self.machine_st.registers[1], cstr);
+ }
+ _ => {
+ self.machine_st.fail = true;
+ return Ok(());
}
}
- &SystemClauseType::LoadLibraryAsStream => {
- let library_name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1])));
+ } else {
+ let mut bytes = vec![];
+ for c in self.machine_st.value_to_str_like(self.machine_st.registers[1]).unwrap().as_str().chars() {
+ if c as u32 > 255 {
+ let stub = functor_stub(atom!("chars_base64"), 3);
+
+ let err = self.machine_st.type_error(
+ ValidType::Byte,
+ char_as_cell!(c),
+ );
- use crate::machine::LIBRARIES;
+ return Err(self.machine_st.error_form(err, stub));
+ }
- match LIBRARIES.borrow().get(library_name.as_str()) {
- Some(library) => {
- let lib_stream = Stream::from_static_string(library, &mut self.machine_st.arena);
- unify!(self.machine_st, stream_as_cell!(lib_stream), self.machine_st.registers[2]);
+ bytes.push(c as u8);
+ }
- let mut path_buf = machine::current_dir();
+ let b64 = base64::encode_config(bytes, config);
+ let cstr = put_complete_string(
+ &mut self.machine_st.heap,
+ &b64,
+ &mut self.machine_st.atom_tbl,
+ );
- path_buf.push("/lib");
- path_buf.push(library_name.as_str());
+ unify!(self.machine_st, self.machine_st.registers[2], cstr);
+ }
- let library_path_str = path_buf.to_str().unwrap();
- let library_path = self.machine_st.atom_tbl.build_with(library_path_str);
+ Ok(())
+ }
- self.machine_st.unify_atom(library_path, self.machine_st.registers[3]);
- }
- None => {
- let stub = functor_stub(atom!("load"), 1);
- let err = self.machine_st.existence_error(
- ExistenceError::ModuleSource(ModuleSource::Library(library_name))
- );
+ #[inline(always)]
+ pub(crate) fn load_library_as_stream(&mut self) -> CallResult {
+ let library_name = cell_as_atom!(self.machine_st.store(self.machine_st.deref(
+ self.machine_st.registers[1]
+ )));
- return Err(self.machine_st.error_form(err, stub));
- }
- }
- }
- &SystemClauseType::DevourWhitespace => {
- let stream = self.machine_st.get_stream_or_alias(
- self.machine_st.registers[1],
- &self.indices.stream_aliases,
- atom!("$devour_whitespace"),
- 1,
- )?;
+ use crate::machine::LIBRARIES;
- match self.machine_st.devour_whitespace(stream) {
- Ok(false) => { // not at EOF.
- }
- _ => {
- self.machine_st.fail = true;
- return Ok(());
- }
- }
- }
- &SystemClauseType::IsSTOEnabled => {
- if self.machine_st.unify_fn as usize == MachineState::unify_with_occurs_check as usize {
- self.machine_st.unify_atom(atom!("true"), self.machine_st.registers[1]);
- } else if self.machine_st.unify_fn as usize
- == MachineState::unify_with_occurs_check_with_error as usize
- {
- self.machine_st.unify_atom(atom!("error"), self.machine_st.registers[1]);
- } else {
- self.machine_st.unify_atom(atom!("false"), self.machine_st.registers[1]);
- }
+ match LIBRARIES.borrow().get(library_name.as_str()) {
+ Some(library) => {
+ let lib_stream = Stream::from_static_string(library, &mut self.machine_st.arena);
+ unify!(self.machine_st, stream_as_cell!(lib_stream), self.machine_st.registers[2]);
+
+ let mut path_buf = machine::current_dir();
+
+ path_buf.push("/lib");
+ path_buf.push(library_name.as_str());
+
+ let library_path_str = path_buf.to_str().unwrap();
+ let library_path = self.machine_st.atom_tbl.build_with(library_path_str);
+
+ self.machine_st.unify_atom(library_path, self.machine_st.registers[3]);
}
- &SystemClauseType::SetSTOAsUnify => {
- self.machine_st.unify_fn = MachineState::unify_with_occurs_check;
- self.machine_st.bind_fn = MachineState::bind_with_occurs_check_wrapper;
+ None => {
+ let stub = functor_stub(atom!("load"), 1);
+ let err = self.machine_st.existence_error(
+ ExistenceError::ModuleSource(ModuleSource::Library(library_name))
+ );
+
+ return Err(self.machine_st.error_form(err, stub));
}
- &SystemClauseType::SetNSTOAsUnify => {
- self.machine_st.unify_fn = MachineState::unify;
- self.machine_st.bind_fn = MachineState::bind;
+ }
+
+ Ok(())
+ }
+
+ #[inline(always)]
+ pub(crate) fn devour_whitespace(&mut self) -> CallResult {
+ let stream = self.machine_st.get_stream_or_alias(
+ self.machine_st.registers[1],
+ &self.indices.stream_aliases,
+ atom!("$devour_whitespace"),
+ 1,
+ )?;
+
+ match self.machine_st.devour_whitespace(stream) {
+ Ok(false) => { // not at EOF.
}
- &SystemClauseType::SetSTOWithErrorAsUnify => {
- self.machine_st.unify_fn = MachineState::unify_with_occurs_check_with_error;
- self.machine_st.bind_fn = MachineState::bind_with_occurs_check_with_error_wrapper;
+ _ => {
+ self.machine_st.fail = true;
}
- &SystemClauseType::HomeDirectory => {
- let path = match dirs_next::home_dir() {
- Some(path) => path,
- None => {
- self.machine_st.fail = true;
- return Ok(());
- }
- };
+ }
- if path.is_dir() {
- if let Some(path) = path.to_str() {
- let path_string = put_complete_string(
- &mut self.machine_st.heap,
- path,
- &mut self.machine_st.atom_tbl,
- );
+ Ok(())
+ }
- unify!(self.machine_st, self.machine_st.registers[1], path_string);
- return return_from_clause!(self.machine_st.last_call, self.machine_st);
- }
- }
+ #[inline(always)]
+ pub(crate) fn is_sto_enabled(&mut self) {
+ if self.machine_st.unify_fn as usize == MachineState::unify_with_occurs_check as usize {
+ self.machine_st.unify_atom(atom!("true"), self.machine_st.registers[1]);
+ } else if self.machine_st.unify_fn as usize
+ == MachineState::unify_with_occurs_check_with_error as usize
+ {
+ self.machine_st.unify_atom(atom!("error"), self.machine_st.registers[1]);
+ } else {
+ self.machine_st.unify_atom(atom!("false"), self.machine_st.registers[1]);
+ }
+ }
+
+ #[inline(always)]
+ pub(crate) fn set_sto_as_unify(&mut self) {
+ self.machine_st.unify_fn = MachineState::unify_with_occurs_check;
+ self.machine_st.bind_fn = MachineState::bind_with_occurs_check_wrapper;
+ }
+
+ #[inline(always)]
+ pub(crate) fn set_nsto_as_unify(&mut self) {
+ self.machine_st.unify_fn = MachineState::unify;
+ self.machine_st.bind_fn = MachineState::bind;
+ }
+
+ #[inline(always)]
+ pub(crate) fn set_sto_with_error_as_unify(&mut self) {
+ self.machine_st.unify_fn = MachineState::unify_with_occurs_check_with_error;
+ self.machine_st.bind_fn = MachineState::bind_with_occurs_check_with_error_wrapper;
+ }
+ #[inline(always)]
+ pub(crate) fn home_directory(&mut self) {
+ let path = match dirs_next::home_dir() {
+ Some(path) => path,
+ None => {
self.machine_st.fail = true;
+ return;
}
- &SystemClauseType::DebugHook => {
- self.machine_st.fail = false;
+ };
+
+ if path.is_dir() {
+ if let Some(path) = path.to_str() {
+ let path_string = put_complete_string(
+ &mut self.machine_st.heap,
+ path,
+ &mut self.machine_st.atom_tbl,
+ );
+
+ unify!(self.machine_st, self.machine_st.registers[1], path_string);
+ return;
}
- &SystemClauseType::PopCount => {
- let number = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
- let pop_count = integer_as_cell!(match Number::try_from(number) {
- Ok(Number::Fixnum(n)) => {
- Number::Fixnum(Fixnum::build_with(n.get_num().count_ones() as i64))
- }
- Ok(Number::Integer(n)) => {
- Number::arena_from(n.count_ones().unwrap(), &mut self.machine_st.arena)
- }
- _ => {
- unreachable!()
- }
- });
+ }
+
+ self.machine_st.fail = true;
+ }
- unify!(self.machine_st, self.machine_st.registers[2], pop_count);
+ pub(crate) fn debug_hook(&mut self) {
+ }
+
+ #[inline(always)]
+ pub(crate) fn pop_count(&mut self) {
+ let number = self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]));
+ let pop_count = integer_as_cell!(match Number::try_from(number) {
+ Ok(Number::Fixnum(n)) => {
+ Number::Fixnum(Fixnum::build_with(n.get_num().count_ones() as i64))
}
- };
+ Ok(Number::Integer(n)) => {
+ Number::arena_from(n.count_ones().unwrap(), &mut self.machine_st.arena)
+ }
+ _ => {
+ unreachable!()
+ }
+ });
- return_from_clause!(self.machine_st.last_call, self.machine_st)
+ unify!(self.machine_st, self.machine_st.registers[2], pop_count);
}
pub(super) fn systemtime_to_timestamp(&mut self, system_time: SystemTime) -> Atom {
let datetime: DateTime<Local> = system_time.into();
let mut fstr = "[".to_string();
- const SPECIFIERS: [&'static str; 19] = [
- "Y", "m", "d", "H", "M", "S", "y", "b", "B", "a", "A", "w", "u", "U", "W", "j", "D",
- "x", "v",
+ const SPECIFIERS: [char; 19] = [
+ 'Y', 'm', 'd', 'H', 'M', 'S', 'y', 'b', 'B', 'a', 'A', 'w', 'u', 'U', 'W', 'j', 'D',
+ 'x', 'v',
];
for spec in SPECIFIERS {
-macro_rules! interm {
- ($n: expr) => {
- ArithmeticTerm::Interm($n)
- };
-}
-
/* A simple macro to count the arguments in a variadic list
* of token trees.
*/
);
}
+macro_rules! compare_number_instr {
+ ($cmp: expr, $at_1: expr, $at_2: expr) => {{
+ $cmp.set_terms($at_1, $at_2);
+ call_clause!(ClauseType::Inlined(InlinedClauseType::CompareNumber($cmp)), 0)
+ }};
+}
+
+macro_rules! call_clause {
+ ($clause_type:expr, $pvs:expr) => {{
+ let mut instr = $clause_type.to_instr();
+ instr.perm_vars_mut().map(|pvs| *pvs = $pvs);
+ instr
+ }};
+}
+
+macro_rules! call_clause_by_default {
+ ($clause_type:expr, $pvs:expr) => {{
+ let mut instr = $clause_type.to_instr().to_default();
+ instr.perm_vars_mut().map(|pvs| *pvs = $pvs);
+ instr
+ }};
+}
+
+macro_rules! interm {
+ ($n: expr) => {
+ ArithmeticTerm::Interm($n)
+ };
+}
+
macro_rules! ar_reg {
($r: expr) => {
ArithmeticTerm::Reg($r)
($code_dir:expr, $op_dir:expr, $modules:expr) => {
IndexStore {
code_dir: $code_dir,
- extensible_predicates: ExtensiblePredicates::new(),
- local_extensible_predicates: LocalExtensiblePredicates::new(),
- global_variables: GlobalVarDir::new(),
- meta_predicates: MetaPredicateDir::new(),
+ extensible_predicates: ExtensiblePredicates::with_hasher(FxBuildHasher::default()),
+ local_extensible_predicates: LocalExtensiblePredicates::with_hasher(FxBuildHasher::default()),
+ global_variables: GlobalVarDir::with_hasher(FxBuildHasher::default()),
+ meta_predicates: MetaPredicateDir::with_hasher(FxBuildHasher::default()),
modules: $modules,
op_dir: $op_dir,
streams: StreamDir::new(),
- stream_aliases: StreamAliasDir::new(),
- }
- };
-}
-
-macro_rules! is_atom {
- ($r:expr) => {
- call_clause!(ClauseType::Inlined(InlinedClauseType::IsAtom($r)), 1, 0)
- };
-}
-
-macro_rules! is_atomic {
- ($r:expr) => {
- call_clause!(ClauseType::Inlined(InlinedClauseType::IsAtomic($r)), 1, 0)
- };
-}
-
-macro_rules! is_integer {
- ($r:expr) => {
- call_clause!(ClauseType::Inlined(InlinedClauseType::IsInteger($r)), 1, 0)
- };
-}
-
-macro_rules! is_compound {
- ($r:expr) => {
- call_clause!(ClauseType::Inlined(InlinedClauseType::IsCompound($r)), 1, 0)
- };
-}
-
-macro_rules! is_float {
- ($r:expr) => {
- call_clause!(ClauseType::Inlined(InlinedClauseType::IsFloat($r)), 1, 0)
- };
-}
-
-macro_rules! is_rational {
- ($r:expr) => {
- call_clause!(ClauseType::Inlined(InlinedClauseType::IsRational($r)), 1, 0)
- };
-}
-
-macro_rules! is_number {
- ($r:expr) => {
- call_clause!(ClauseType::Inlined(InlinedClauseType::IsNumber($r)), 1, 0)
- };
-}
-
-macro_rules! is_nonvar {
- ($r:expr) => {
- call_clause!(ClauseType::Inlined(InlinedClauseType::IsNonVar($r)), 1, 0)
- };
-}
-
-macro_rules! is_var {
- ($r:expr) => {
- call_clause!(ClauseType::Inlined(InlinedClauseType::IsVar($r)), 1, 0)
- };
-}
-
-macro_rules! call_clause {
- ($ct:expr, $arity:expr, $pvs:expr) => {
- Line::Control(ControlInstruction::CallClause(
- $ct, $arity, $pvs, false, false,
- ))
- };
- ($ct:expr, $arity:expr, $pvs:expr, $lco:expr) => {
- Line::Control(ControlInstruction::CallClause(
- $ct, $arity, $pvs, $lco, false,
- ))
- };
-}
-
-macro_rules! call_clause_by_default {
- ($ct:expr, $arity:expr, $pvs:expr) => {
- Line::Control(ControlInstruction::CallClause(
- $ct, $arity, $pvs, false, true,
- ))
- };
- ($ct:expr, $arity:expr, $pvs:expr, $lco:expr) => {
- Line::Control(ControlInstruction::CallClause(
- $ct, $arity, $pvs, $lco, true,
- ))
- };
-}
-
-macro_rules! proceed {
- () => {
- Line::Control(ControlInstruction::Proceed)
- };
-}
-
-macro_rules! is_call {
- ($r:expr, $at:expr) => {
- call_clause!(ClauseType::BuiltIn(BuiltInClauseType::Is($r, $at)), 2, 0)
- };
-}
-
-macro_rules! is_call_by_default {
- ($r:expr, $at:expr) => {
- call_clause_by_default!(ClauseType::BuiltIn(BuiltInClauseType::Is($r, $at)), 2, 0)
- };
-}
-
-macro_rules! set_cp {
- ($r:expr) => {
- call_clause!(ClauseType::System(SystemClauseType::SetCutPoint($r)), 1, 0)
- };
-}
-
-macro_rules! succeed {
- () => {
- call_clause!(ClauseType::System(SystemClauseType::Succeed), 0, 0)
- };
-}
-
-macro_rules! fail {
- () => {
- call_clause!(ClauseType::System(SystemClauseType::Fail), 0, 0)
- };
-}
-
-macro_rules! compare_number_instr {
- ($cmp: expr, $at_1: expr, $at_2: expr) => {{
- let ct = ClauseType::Inlined(InlinedClauseType::CompareNumber($cmp, $at_1, $at_2));
- call_clause!(ct, 2, 0)
- }};
-}
-
-macro_rules! jmp_call {
- ($arity:expr, $offset:expr, $pvs:expr) => {
- Line::Control(ControlInstruction::JmpBy($arity, $offset, $pvs, false))
- };
-}
-
-macro_rules! return_from_clause {
- ($lco:expr, $machine_st:expr) => {{
- if let CodePtr::VerifyAttrInterrupt(_) = $machine_st.p {
- return Ok(());
- }
-
- if $lco {
- $machine_st.p = CodePtr::Local($machine_st.cp);
- } else {
- $machine_st.p += 1;
- }
-
- Ok(())
- }};
-}
-
-macro_rules! dir_entry {
- ($idx:expr) => {
- LocalCodePtr::DirEntry($idx)
- };
-}
-
-macro_rules! put_constant {
- ($lvl:expr, $cons:expr, $r:expr) => {
- QueryInstruction::PutConstant($lvl, $cons, $r)
- };
-}
-
-macro_rules! get_level_and_unify {
- ($r: expr) => {
- Line::Cut(CutInstruction::GetLevelAndUnify($r))
- };
-}
-
-/*
-macro_rules! unwind_protect {
- ($e: expr, $protected: expr) => {
- match $e {
- Err(e) => {
- $protected;
- return Err(e);
- }
- _ => {}
- }
- };
-}
-*/
-/*
-macro_rules! discard_result {
- ($f: expr) => {
- match $f {
- _ => (),
+ stream_aliases: StreamAliasDir::with_hasher(FxBuildHasher::default()),
}
};
}
-*/
-
-macro_rules! try_or_fail {
- ($s:expr, $e:expr) => {{
- match $e {
- Ok(val) => val,
- Err(msg) => {
- $s.throw_exception(msg);
- return;
- }
- }
- }};
-}
-
-macro_rules! try_or_fail_gen {
- ($s:expr, $e:expr) => {{
- match $e {
- Ok(val) => val,
- Err(msg_fn) => {
- let e = msg_fn($s);
- $s.throw_exception(e);
- return;
- }
- }
- }};
-}
macro_rules! unify {
($machine_st:expr, $($value:expr),*) => {{
use rug::{Integer, Rational};
+use fxhash::FxBuildHasher;
use indexmap::IndexMap;
use modular_bitfield::error::OutOfBounds;
use modular_bitfield::prelude::*;
}
// name and fixity -> operator type and precedence.
-pub type OpDir = IndexMap<(Atom, Fixity), OpDesc>;
+pub type OpDir = IndexMap<(Atom, Fixity), OpDesc, FxBuildHasher>;
#[derive(Debug, Clone, Copy)]
pub struct MachineFlags {
}
pub fn default_op_dir() -> OpDir {
- let mut op_dir = OpDir::new();
+ let mut op_dir = OpDir::with_hasher(FxBuildHasher::default());
op_dir.insert(
(atom!(":-"), Fixity::In),
use crate::parser::char_reader::*;
use crate::types::*;
+use fxhash::FxBuildHasher;
+
use rustyline::error::ReadlineError;
use rustyline::{Cmd, Config, Editor, KeyEvent};
heap,
atom_tbl,
queue: SubtermDeque::new(),
- var_dict: HeapVarDict::new(),
+ var_dict: HeapVarDict::with_hasher(FxBuildHasher::default()),
}
}
use crate::parser::ast::*;
use crate::atom_table::*;
-use crate::clause_types::*;
use crate::forms::*;
use crate::instructions::*;
use crate::iterators::*;
use crate::types::*;
+pub(crate) struct FactInstruction;
+pub(crate) struct QueryInstruction;
+
pub(crate) trait CompilationTarget<'a> {
type Iterator: Iterator<Item = TermRef<'a>>;
fn iter(term: &'a Term) -> Self::Iterator;
- fn to_constant(lvl: Level, literal: Literal, r: RegType) -> Self;
- fn to_list(lvl: Level, r: RegType) -> Self;
- fn to_structure(ct: ClauseType, arity: usize, r: RegType) -> Self;
+ fn to_constant(lvl: Level, literal: Literal, r: RegType) -> Instruction;
+ fn to_list(lvl: Level, r: RegType) -> Instruction;
+ fn to_structure(name: Atom, arity: usize, r: RegType) -> Instruction;
- fn to_void(num_subterms: usize) -> Self;
- fn is_void_instr(&self) -> bool;
+ fn to_void(num_subterms: usize) -> Instruction;
+ fn is_void_instr(instr: &Instruction) -> bool;
- fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Self;
+ fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction;
- fn incr_void_instr(&mut self);
+ fn incr_void_instr(instr: &mut Instruction);
- fn constant_subterm(literal: Literal) -> Self;
+ fn constant_subterm(literal: Literal) -> Instruction;
- fn argument_to_variable(r: RegType, r: usize) -> Self;
- fn argument_to_value(r: RegType, val: usize) -> Self;
+ fn argument_to_variable(r: RegType, r: usize) -> Instruction;
+ fn argument_to_value(r: RegType, val: usize) -> Instruction;
- fn move_to_register(r: RegType, val: usize) -> Self;
+ fn move_to_register(r: RegType, val: usize) -> Instruction;
- fn subterm_to_variable(r: RegType) -> Self;
- fn subterm_to_value(r: RegType) -> Self;
+ fn subterm_to_variable(r: RegType) -> Instruction;
+ fn subterm_to_value(r: RegType) -> Instruction;
- fn clause_arg_to_instr(r: RegType) -> Self;
+ fn clause_arg_to_instr(r: RegType) -> Instruction;
}
impl<'a> CompilationTarget<'a> for FactInstruction {
breadth_first_iter(term, false) // do not iterate over the root clause if one exists.
}
- fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Self {
- FactInstruction::GetConstant(lvl, HeapCellValue::from(constant), reg)
+ fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Instruction {
+ Instruction::GetConstant(lvl, HeapCellValue::from(constant), reg)
}
- fn to_structure(ct: ClauseType, arity: usize, reg: RegType) -> Self {
- FactInstruction::GetStructure(ct, arity, reg)
+ fn to_structure(name: Atom, arity: usize, reg: RegType) -> Instruction {
+ Instruction::GetStructure(name, arity, reg)
}
- fn to_list(lvl: Level, reg: RegType) -> Self {
- FactInstruction::GetList(lvl, reg)
+ fn to_list(lvl: Level, reg: RegType) -> Instruction {
+ Instruction::GetList(lvl, reg)
}
- fn to_void(num_subterms: usize) -> Self {
- FactInstruction::UnifyVoid(num_subterms)
+ fn to_void(num_subterms: usize) -> Instruction {
+ Instruction::UnifyVoid(num_subterms)
}
- fn is_void_instr(&self) -> bool {
- match self {
- &FactInstruction::UnifyVoid(_) => true,
+ fn is_void_instr(instr: &Instruction) -> bool {
+ match instr {
+ &Instruction::UnifyVoid(_) => true,
_ => false,
}
}
- fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Self {
- FactInstruction::GetPartialString(lvl, string, r, has_tail)
+ fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction {
+ Instruction::GetPartialString(lvl, string, r, has_tail)
}
- fn incr_void_instr(&mut self) {
- match self {
- &mut FactInstruction::UnifyVoid(ref mut incr) => *incr += 1,
+ fn incr_void_instr(instr: &mut Instruction) {
+ match instr {
+ &mut Instruction::UnifyVoid(ref mut incr) => *incr += 1,
_ => {}
}
}
- fn constant_subterm(constant: Literal) -> Self {
- FactInstruction::UnifyConstant(HeapCellValue::from(constant))
+ fn constant_subterm(constant: Literal) -> Instruction {
+ Instruction::UnifyConstant(HeapCellValue::from(constant))
}
- fn argument_to_variable(arg: RegType, val: usize) -> Self {
- FactInstruction::GetVariable(arg, val)
+ fn argument_to_variable(arg: RegType, val: usize) -> Instruction {
+ Instruction::GetVariable(arg, val)
}
- fn move_to_register(arg: RegType, val: usize) -> Self {
- FactInstruction::GetVariable(arg, val)
+ fn move_to_register(arg: RegType, val: usize) -> Instruction {
+ Instruction::GetVariable(arg, val)
}
- fn argument_to_value(arg: RegType, val: usize) -> Self {
- FactInstruction::GetValue(arg, val)
+ fn argument_to_value(arg: RegType, val: usize) -> Instruction {
+ Instruction::GetValue(arg, val)
}
- fn subterm_to_variable(val: RegType) -> Self {
- FactInstruction::UnifyVariable(val)
+ fn subterm_to_variable(val: RegType) -> Instruction {
+ Instruction::UnifyVariable(val)
}
- fn subterm_to_value(val: RegType) -> Self {
- FactInstruction::UnifyValue(val)
+ fn subterm_to_value(val: RegType) -> Instruction {
+ Instruction::UnifyValue(val)
}
- fn clause_arg_to_instr(val: RegType) -> Self {
- FactInstruction::UnifyVariable(val)
+ fn clause_arg_to_instr(val: RegType) -> Instruction {
+ Instruction::UnifyVariable(val)
}
}
post_order_iter(term)
}
- fn to_structure(ct: ClauseType, arity: usize, r: RegType) -> Self {
- QueryInstruction::PutStructure(ct, arity, r)
+ fn to_structure(name: Atom, arity: usize, r: RegType) -> Instruction {
+ Instruction::PutStructure(name, arity, r)
}
- fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Self {
- QueryInstruction::PutConstant(lvl, HeapCellValue::from(constant), reg)
+ fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Instruction {
+ Instruction::PutConstant(lvl, HeapCellValue::from(constant), reg)
}
- fn to_list(lvl: Level, reg: RegType) -> Self {
- QueryInstruction::PutList(lvl, reg)
+ fn to_list(lvl: Level, reg: RegType) -> Instruction {
+ Instruction::PutList(lvl, reg)
}
- fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Self {
- QueryInstruction::PutPartialString(lvl, string, r, has_tail)
+ fn to_pstr(lvl: Level, string: Atom, r: RegType, has_tail: bool) -> Instruction {
+ Instruction::PutPartialString(lvl, string, r, has_tail)
}
- fn to_void(subterms: usize) -> Self {
- QueryInstruction::SetVoid(subterms)
+ fn to_void(subterms: usize) -> Instruction {
+ Instruction::SetVoid(subterms)
}
- fn is_void_instr(&self) -> bool {
- match self {
- &QueryInstruction::SetVoid(_) => true,
+ fn is_void_instr(instr: &Instruction) -> bool {
+ match instr {
+ &Instruction::SetVoid(_) => true,
_ => false,
}
}
- fn incr_void_instr(&mut self) {
- match self {
- &mut QueryInstruction::SetVoid(ref mut incr) => *incr += 1,
+ fn incr_void_instr(instr: &mut Instruction) {
+ match instr {
+ &mut Instruction::SetVoid(ref mut incr) => *incr += 1,
_ => {}
}
}
- fn constant_subterm(constant: Literal) -> Self {
- QueryInstruction::SetConstant(HeapCellValue::from(constant))
+ fn constant_subterm(constant: Literal) -> Instruction {
+ Instruction::SetConstant(HeapCellValue::from(constant))
}
- fn argument_to_variable(arg: RegType, val: usize) -> Self {
- QueryInstruction::PutVariable(arg, val)
+ fn argument_to_variable(arg: RegType, val: usize) -> Instruction {
+ Instruction::PutVariable(arg, val)
}
- fn move_to_register(arg: RegType, val: usize) -> Self {
- QueryInstruction::GetVariable(arg, val)
+ fn move_to_register(arg: RegType, val: usize) -> Instruction {
+ Instruction::GetVariable(arg, val)
}
- fn argument_to_value(arg: RegType, val: usize) -> Self {
- QueryInstruction::PutValue(arg, val)
+ fn argument_to_value(arg: RegType, val: usize) -> Instruction {
+ Instruction::PutValue(arg, val)
}
- fn subterm_to_variable(val: RegType) -> Self {
- QueryInstruction::SetVariable(val)
+ fn subterm_to_variable(val: RegType) -> Instruction {
+ Instruction::SetVariable(val)
}
- fn subterm_to_value(val: RegType) -> Self {
- QueryInstruction::SetValue(val)
+ fn subterm_to_value(val: RegType) -> Instruction {
+ Instruction::SetValue(val)
}
- fn clause_arg_to_instr(val: RegType) -> Self {
- QueryInstruction::SetValue(val)
+ fn clause_arg_to_instr(val: RegType) -> Instruction {
+ Instruction::SetValue(val)
}
}
( Item == user ->
catch(load(user_input), E, print_exception_with_check(E))
;
- submit_query_and_print_results(consult(Item), [])
+ submit_query_and_print_results(consult(Item), [])
)
; catch(type_error(atom, Item, repl/0),
E,
submit_query_and_print_results(Term0, VarList) :-
( functor(Term0, call, _) ->
Term = Term0 % prevent pre-mature expansion of incomplete goal
- % in the first argument, which is done by call/N
+ % in the first argument, which is done by call/N
; expand_goal(Term0, user, Term)
),
setup_call_cleanup(bb_put('$first_answer', true),
use crate::arena::*;
use crate::atom_table::*;
-use crate::clause_types::*;
use crate::forms::*;
use crate::instructions::*;
use crate::machine::loader::CompilationTarget;
use std::fmt;
-impl fmt::Display for LocalCodePtr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- LocalCodePtr::DirEntry(p) => write!(f, "LocalCodePtr::DirEntry({})", p),
- LocalCodePtr::Halt => write!(f, "LocalCodePtr::Halt"),
- // LocalCodePtr::IndexingBuf(p, o, i) => {
- // write!(f, "LocalCodePtr::IndexingBuf({}, {}, {})", p, o, i)
- // }
- }
- }
-}
-
+/*
impl fmt::Display for REPLCodePtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
}
}
}
+*/
impl fmt::Display for IndexPtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
+/*
impl fmt::Display for FactInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
}
}
}
+*/
impl fmt::Display for HeapCellValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
unreachable!()
}
)
- /*
- match self {
- &HeapCellValue::Addr(ref addr) => write!(f, "{}", addr),
- &HeapCellValue::Atom(ref atom, _) => write!(f, "{}", atom.as_str()),
- &HeapCellValue::DBRef(ref db_ref) => write!(f, "{}", db_ref),
- &HeapCellValue::Integer(ref n) => write!(f, "{}", n),
- &HeapCellValue::LoadStatePayload(_) => write!(f, "LoadStatePayload"),
- &HeapCellValue::Rational(ref n) => write!(f, "{}", n),
- &HeapCellValue::NamedStr(arity, ref name, Some(ref cell)) => write!(
- f,
- "{}/{} (op, priority: {}, spec: {})",
- name.as_str(),
- arity,
- cell.prec(),
- cell.assoc()
- ),
- &HeapCellValue::NamedStr(arity, ref name, None) => {
- write!(f, "{}/{}", name.as_str(), arity)
- }
- &HeapCellValue::PartialString(ref pstr, has_tail) => {
- write!(
- f,
- "pstr ( buf: \"{}\", has_tail({}) )",
- pstr.as_str_from(0),
- has_tail,
- )
- }
- &HeapCellValue::Stream(ref stream) => {
- write!(f, "$stream({})", stream.as_ptr() as usize)
- }
- &HeapCellValue::TcpListener(ref tcp_listener) => {
- write!(f, "$tcp_listener({})", tcp_listener.local_addr().unwrap())
- }
- }
- */
}
}
/*
-impl fmt::Display for DBRef {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- &DBRef::NamedPred(ref name, arity, _) => write!(f, "db_ref:named:{}/{}", name, arity),
- &DBRef::Op(priority, spec, ref name, ..) => {
- write!(f, "db_ref:op({}, {}, {})", priority, spec, name)
- }
- }
- }
-}
-*/
-
-/*
-impl fmt::Display for Addr {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- &Addr::Char(c) => write!(f, "Addr::Char({})", c),
- &Addr::EmptyList => write!(f, "Addr::EmptyList"),
- &Addr::Fixnum(n) => write!(f, "Addr::Fixnum({})", n),
- &Addr::Float(fl) => write!(f, "Addr::Float({})", fl),
- &Addr::CutPoint(cp) => write!(f, "Addr::CutPoint({})", cp),
- &Addr::Con(ref c) => write!(f, "Addr::Con({})", c),
- &Addr::Lis(l) => write!(f, "Addr::Lis({})", l),
- &Addr::LoadStatePayload(s) => write!(f, "Addr::LoadStatePayload({})", s),
- &Addr::AttrVar(h) => write!(f, "Addr::AttrVar({})", h),
- &Addr::HeapCell(h) => write!(f, "Addr::HeapCell({})", h),
- &Addr::StackCell(fr, sc) => write!(f, "Addr::StackCell({}, {})", fr, sc),
- &Addr::Str(s) => write!(f, "Addr::Str({})", s),
- &Addr::PStrLocation(h, n) => write!(f, "Addr::PStrLocation({}, {})", h, n),
- &Addr::Stream(stream) => write!(f, "Addr::Stream({})", stream),
- &Addr::TcpListener(tcp_listener) => write!(f, "Addr::TcpListener({})", tcp_listener),
- &Addr::Usize(cp) => write!(f, "Addr::Usize({})", cp),
- }
- }
-}
-*/
-
impl fmt::Display for ControlInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
}
}
}
+*/
impl fmt::Display for IndexedChoiceInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
+/*
impl fmt::Display for ChoiceInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
}
}
}
+*/
impl fmt::Display for IndexingCodePtr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
+/*
impl fmt::Display for Line {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
}
}
}
-
-impl fmt::Display for Number {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- Number::Float(fl) => write!(f, "{}", fl),
- Number::Integer(n) => write!(f, "{}", n),
- Number::Rational(r) => write!(f, "{}", r),
- Number::Fixnum(n) => write!(f, "{}", n.get_num()),
- }
- }
-}
+*/
+/*
impl fmt::Display for ArithmeticTerm {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
}
-
+*/
+/*
impl fmt::Display for Level {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
}
}
}
+*/