]> Repositorios git - scryer-prolog.git/commitdiff
implement new disjunction compilation
authorMark <[email protected]>
Sat, 17 Jun 2023 22:28:56 +0000 (16:28 -0600)
committerMark <[email protected]>
Fri, 23 Jun 2023 20:11:31 +0000 (14:11 -0600)
32 files changed:
Cargo.lock
Cargo.toml
build/instructions_template.rs
src/allocator.rs
src/arithmetic.rs
src/codegen.rs
src/debray_allocator.rs
src/fixtures.rs [deleted file]
src/forms.rs
src/heap_iter.rs
src/heap_print.rs
src/iterators.rs
src/lib.rs
src/lib/builtins.pl
src/lib/format.pl
src/loader.pl
src/machine/code_walker.rs
src/machine/compile.rs
src/machine/disjuncts.rs
src/machine/dispatch.rs
src/machine/load_state.rs
src/machine/loader.rs
src/machine/machine_indices.rs
src/machine/machine_state.rs
src/machine/mod.rs
src/machine/preprocessor.rs
src/machine/system_calls.rs
src/macros.rs
src/parser/ast.rs
src/parser/parser.rs
src/read.rs
src/targets.rs

index 542afd09677c213e6d9fc033e25469c1cc475a40..8b4fc8a95c73829112938d92f7ced2d79def6846 100644 (file)
@@ -79,6 +79,18 @@ version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
+[[package]]
+name = "bitvec"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
+dependencies = [
+ "funty",
+ "radium",
+ "tap",
+ "wyz",
+]
+
 [[package]]
 name = "blake2"
 version = "0.8.1"
@@ -536,6 +548,12 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
 
+[[package]]
+name = "funty"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
+
 [[package]]
 name = "futf"
 version = "0.1.5"
@@ -1526,6 +1544,12 @@ dependencies = [
  "proc-macro2 1.0.47",
 ]
 
+[[package]]
+name = "radium"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
+
 [[package]]
 name = "radix_trie"
 version = "0.2.1"
@@ -1856,6 +1880,7 @@ dependencies = [
  "assert_cmd",
  "base64",
  "bit-set",
+ "bitvec",
  "blake2 0.8.1",
  "chrono",
  "cpu-time",
@@ -2203,6 +2228,12 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "tap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+
 [[package]]
 name = "tempfile"
 version = "3.3.0"
@@ -2592,21 +2623,6 @@ dependencies = [
  "windows_x86_64_msvc 0.36.1",
 ]
 
-[[package]]
-name = "windows-sys"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
-dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc 0.42.0",
- "windows_i686_gnu 0.42.0",
- "windows_i686_msvc 0.42.0",
- "windows_x86_64_gnu 0.42.0",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc 0.42.0",
-]
-
 [[package]]
 name = "windows-sys"
 version = "0.42.0"
@@ -2628,24 +2644,12 @@ version = "0.42.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
 
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.30.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
-
 [[package]]
 name = "windows_aarch64_msvc"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
 
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
-
 [[package]]
 name = "windows_aarch64_msvc"
 version = "0.42.1"
@@ -2658,12 +2662,6 @@ version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
 
-[[package]]
-name = "windows_i686_gnu"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
-
 [[package]]
 name = "windows_i686_gnu"
 version = "0.42.1"
@@ -2676,12 +2674,6 @@ version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
 
-[[package]]
-name = "windows_i686_msvc"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
-
 [[package]]
 name = "windows_i686_msvc"
 version = "0.42.1"
@@ -2694,18 +2686,6 @@ version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
 
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
-
 [[package]]
 name = "windows_x86_64_gnu"
 version = "0.42.1"
@@ -2714,9 +2694,9 @@ checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.42.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
+checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
 
 [[package]]
 name = "windows_x86_64_msvc"
@@ -2726,15 +2706,18 @@ checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.42.0"
+version = "0.42.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
+checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
 
 [[package]]
-name = "windows_x86_64_msvc"
-version = "0.42.1"
+name = "wyz"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
+checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
+dependencies = [
+ "tap",
+]
 
 [[package]]
 name = "xmlparser"
index f358126aa99a623afb5020ad2fea679a3e4091bc..1f4fa7aad181df275adb7b5cf94b278818f6f083 100644 (file)
@@ -28,6 +28,7 @@ walkdir = "2"
 
 [dependencies]
 bit-set = "0.5.3"
+bitvec = "1"
 cpu-time = "1.0.0"
 crossterm = "0.20.0"
 dirs-next = "2.0.0"
index d0a8c4d0ec7734066f35ca3f590d72956bd81c29..25036607aefb3f6219f84d7998a71a2dc984fe91 100644 (file)
@@ -639,6 +639,10 @@ enum InstructionTemplate {
     Cut(RegType),
     #[strum_discriminants(strum(props(Arity = "1", Name = "get_level")))]
     GetLevel(RegType),
+    #[strum_discriminants(strum(props(Arity = "1", Name = "get_prev_level")))]
+    GetPrevLevel(RegType),
+    #[strum_discriminants(strum(props(Arity = "1", Name = "get_cut_point")))]
+    GetCutPoint(RegType),
     #[strum_discriminants(strum(props(Arity = "0", Name = "neck_cut")))]
     NeckCut,
     // choice instruction
@@ -740,10 +744,8 @@ enum InstructionTemplate {
     Allocate(usize), // num_frames.
     #[strum_discriminants(strum(props(Arity = "0", Name = "deallocate")))]
     Deallocate,
-    #[strum_discriminants(strum(props(Arity = "arity", Name = "jmp_by_call")))]
-    JmpByCall(usize, usize), // arity, relative offset.
-    #[strum_discriminants(strum(props(Arity = "arity", Name = "jmp_by_execute")))]
-    JmpByExecute(usize, usize), // arity, relative offset.
+    #[strum_discriminants(strum(props(Arity = "1", Name = "jmp_by_call")))]
+    JmpByCall(usize), // relative offset.
     #[strum_discriminants(strum(props(Arity = "1", Name = "rev_jmp_by")))]
     RevJmpBy(usize),
     #[strum_discriminants(strum(props(Arity = "0", Name = "proceed")))]
@@ -1114,6 +1116,7 @@ fn generate_instruction_preface() -> TokenStream {
         }
 
         pub type Code = Vec<Instruction>;
+        pub type CodeDeque = VecDeque<Instruction>;
 
         impl Instruction {
             #[inline]
@@ -1296,6 +1299,14 @@ fn generate_instruction_preface() -> TokenStream {
                         let rt_stub = reg_type_into_functor(r);
                         functor!(atom!("get_level"), [str(h, 0)], [rt_stub])
                     }
+                    &Instruction::GetPrevLevel(r) => {
+                        let rt_stub = reg_type_into_functor(r);
+                        functor!(atom!("get_prev_level"), [str(h, 0)], [rt_stub])
+                    }
+                    &Instruction::GetCutPoint(r) => {
+                        let rt_stub = reg_type_into_functor(r);
+                        functor!(atom!("get_cut_point"), [str(h, 0)], [rt_stub])
+                    }
                     &Instruction::NeckCut => {
                         functor!(atom!("neck_cut"))
                     }
@@ -1449,30 +1460,30 @@ fn generate_instruction_preface() -> TokenStream {
                     &Instruction::DefaultExecuteNamed(arity, name, ..) => {
                         functor!(atom!("execute_default"), [atom(name), fixnum(arity)])
                     }
-                    &Instruction::CallN(arity, _) => {
+                    &Instruction::CallN(arity) => {
                         functor!(atom!("call_n"), [fixnum(arity)])
                     }
-                    &Instruction::ExecuteN(arity, _) => {
+                    &Instruction::ExecuteN(arity) => {
                         functor!(atom!("execute_n"), [fixnum(arity)])
                     }
-                    &Instruction::DefaultCallN(arity, _) => {
+                    &Instruction::DefaultCallN(arity) => {
                         functor!(atom!("call_default_n"), [fixnum(arity)])
                     }
-                    &Instruction::DefaultExecuteN(arity, _) => {
+                    &Instruction::DefaultExecuteN(arity) => {
                         functor!(atom!("execute_default_n"), [fixnum(arity)])
                     }
-                    &Instruction::CallInlineCallN(arity, _) => {
+                    &Instruction::CallInlineCallN(arity) => {
                         functor!(atom!("call_n_inline"), [fixnum(arity)])
                     }
-                    &Instruction::ExecuteInlineCallN(arity, _) => {
+                    &Instruction::ExecuteInlineCallN(arity) => {
                         functor!(atom!("call_n_inline"), [fixnum(arity)])
                     }
-                    &Instruction::CallTermGreaterThan(_) |
-                    &Instruction::CallTermLessThan(_) |
-                    &Instruction::CallTermGreaterThanOrEqual(_) |
-                    &Instruction::CallTermLessThanOrEqual(_) |
-                    &Instruction::CallTermEqual(_) |
-                    &Instruction::CallTermNotEqual(_) |
+                    &Instruction::CallTermGreaterThan |
+                    &Instruction::CallTermLessThan |
+                    &Instruction::CallTermGreaterThanOrEqual |
+                    &Instruction::CallTermLessThanOrEqual |
+                    &Instruction::CallTermEqual |
+                    &Instruction::CallTermNotEqual |
                     &Instruction::CallNumberGreaterThan(..) |
                     &Instruction::CallNumberLessThan(..) |
                     &Instruction::CallNumberGreaterThanOrEqual(..) |
@@ -1480,563 +1491,561 @@ fn generate_instruction_preface() -> TokenStream {
                     &Instruction::CallNumberEqual(..) |
                     &Instruction::CallNumberNotEqual(..) |
                     &Instruction::CallIs(..) |
-                    &Instruction::CallAcyclicTerm(_) |
-                    &Instruction::CallArg(_) |
-                    &Instruction::CallCompare(_) |
-                    &Instruction::CallCopyTerm(_) |
-                    &Instruction::CallFunctor(_) |
-                    &Instruction::CallGround(_) |
-                    &Instruction::CallKeySort(_) |
-                    &Instruction::CallRead(_) |
-                    &Instruction::CallSort(_) => {
+                    &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::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::ExecuteAcyclicTerm |
+                    &Instruction::ExecuteArg |
+                    &Instruction::ExecuteCompare |
+                    &Instruction::ExecuteCopyTerm |
+                    &Instruction::ExecuteFunctor |
+                    &Instruction::ExecuteGround |
                     &Instruction::ExecuteIs(..) |
-                    &Instruction::ExecuteKeySort(_) |
-                    &Instruction::ExecuteRead(_) |
-                    &Instruction::ExecuteSort(_) => {
+                    &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::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::DefaultCallAcyclicTerm |
+                    &Instruction::DefaultCallArg |
+                    &Instruction::DefaultCallCompare |
+                    &Instruction::DefaultCallCopyTerm |
+                    &Instruction::DefaultCallFunctor |
+                    &Instruction::DefaultCallGround |
                     &Instruction::DefaultCallIs(..) |
-                    &Instruction::DefaultCallKeySort(_) |
-                    &Instruction::DefaultCallRead(_) |
-                    &Instruction::DefaultCallSort(_) => {
+                    &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::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::DefaultExecuteAcyclicTerm |
+                    &Instruction::DefaultExecuteArg |
+                    &Instruction::DefaultExecuteCompare |
+                    &Instruction::DefaultExecuteCopyTerm |
+                    &Instruction::DefaultExecuteFunctor |
+                    &Instruction::DefaultExecuteGround |
                     &Instruction::DefaultExecuteIs(..) |
-                    &Instruction::DefaultExecuteKeySort(_) |
-                    &Instruction::DefaultExecuteRead(_) |
-                    &Instruction::DefaultExecuteSort(_) => {
+                    &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(_, _) => {
+                    &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(_, _) => {
+                    &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::CallFileCopy(_) |
-                    &Instruction::CallWorkingDirectory(_) |
-                    &Instruction::CallDeleteDirectory(_) |
-                    &Instruction::CallPathCanonical(_) |
-                    &Instruction::CallFileTime(_) |
+                    &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::CallFileCopy |
+                    &Instruction::CallWorkingDirectory |
+                    &Instruction::CallDeleteDirectory |
+                    &Instruction::CallPathCanonical |
+                    &Instruction::CallFileTime |
                     &Instruction::CallDynamicModuleResolution(..) |
                     &Instruction::CallPrepareCallClause(..) |
-                    &Instruction::CallCompileInlineOrExpandedGoal(..) |
-                    &Instruction::CallIsExpandedOrInlined(_) |
-                    &Instruction::CallGetClauseP(_) |
-                    &Instruction::CallInvokeClauseAtP(_) |
-                    &Instruction::CallGetFromAttributedVarList(_) |
-                    &Instruction::CallPutToAttributedVarList(_) |
-                    &Instruction::CallDeleteFromAttributedVarList(_) |
-                    &Instruction::CallDeleteAllAttributesFromVar(_) |
-                    &Instruction::CallUnattributedVar(_) |
-                    &Instruction::CallGetDBRefs(_) |
-                    &Instruction::CallEnqueueAttributedVar(_) |
-                    &Instruction::CallFetchGlobalVar(_) |
-                    &Instruction::CallFirstStream(_) |
-                    &Instruction::CallFlushOutput(_) |
-                    &Instruction::CallGetByte(_) |
-                    &Instruction::CallGetChar(_) |
-                    &Instruction::CallGetNChars(_) |
-                    &Instruction::CallGetCode(_) |
-                    &Instruction::CallGetSingleChar(_) |
-                    &Instruction::CallTruncateIfNoLiftedHeapGrowthDiff(_) |
-                    &Instruction::CallTruncateIfNoLiftedHeapGrowth(_) |
-                    &Instruction::CallGetAttributedVariableList(_) |
-                    &Instruction::CallGetAttrVarQueueDelimiter(_) |
-                    &Instruction::CallGetAttrVarQueueBeyond(_) |
-                    &Instruction::CallGetBValue(_) |
-                    &Instruction::CallGetContinuationChunk(_) |
-                    &Instruction::CallGetNextOpDBRef(_) |
-                    &Instruction::CallLookupDBRef(_) |
-                    &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::CallCompileInlineOrExpandedGoal |
+                    &Instruction::CallIsExpandedOrInlined |
+                    &Instruction::CallGetClauseP |
+                    &Instruction::CallInvokeClauseAtP |
+                    &Instruction::CallGetFromAttributedVarList |
+                    &Instruction::CallPutToAttributedVarList |
+                    &Instruction::CallDeleteFromAttributedVarList |
+                    &Instruction::CallDeleteAllAttributesFromVar |
+                    &Instruction::CallUnattributedVar |
+                    &Instruction::CallGetDBRefs |
+                    &Instruction::CallFetchGlobalVar |
+                    &Instruction::CallFirstStream |
+                    &Instruction::CallFlushOutput |
+                    &Instruction::CallGetByte |
+                    &Instruction::CallGetChar |
+                    &Instruction::CallGetNChars |
+                    &Instruction::CallGetCode |
+                    &Instruction::CallGetSingleChar |
+                    &Instruction::CallTruncateIfNoLiftedHeapGrowthDiff |
+                    &Instruction::CallTruncateIfNoLiftedHeapGrowth |
+                    &Instruction::CallGetAttributedVariableList |
+                    &Instruction::CallGetAttrVarQueueDelimiter |
+                    &Instruction::CallGetAttrVarQueueBeyond |
+                    &Instruction::CallGetBValue |
+                    &Instruction::CallGetContinuationChunk |
+                    &Instruction::CallGetNextOpDBRef |
+                    &Instruction::CallLookupDBRef |
+                    &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::CallFail(_) |
-                    &Instruction::CallGetBall(_) |
-                    &Instruction::CallGetCurrentBlock(_) |
-                    &Instruction::CallGetCutPoint(_) |
-                    &Instruction::CallGetDoubleQuotes(_) |
-                    &Instruction::CallInstallNewBlock(_) |
-                    &Instruction::CallMaybe(_) |
-                    &Instruction::CallCpuNow(_) |
-                    &Instruction::CallDeterministicLengthRundown(_) |
-                    &Instruction::CallHttpOpen(_) |
-                    &Instruction::CallHttpListen(_) |
-                    &Instruction::CallHttpAccept(_) |
-                    &Instruction::CallHttpAnswer(_) |
-                   &Instruction::CallLoadForeignLib(_) |
-                   &Instruction::CallForeignCall(_) |
-                   &Instruction::CallDefineForeignStruct(_) |
-                    &Instruction::CallPredicateDefined(_) |
-                    &Instruction::CallStripModule(_) |
-                    &Instruction::CallCurrentTime(_) |
-                    &Instruction::CallQuotedToken(_) |
-                    &Instruction::CallReadTermFromChars(_) |
-                    &Instruction::CallResetBlock(_) |
-                    &Instruction::CallReturnFromVerifyAttr(_) |
-                    &Instruction::CallSetBall(_) |
-                    &Instruction::CallPushBallStack(_) |
-                    &Instruction::CallPopBallStack(_) |
-                    &Instruction::CallPopFromBallStack(_) |
+                    &Instruction::CallSetInput |
+                    &Instruction::CallSetOutput |
+                    &Instruction::CallStoreBacktrackableGlobalVar |
+                    &Instruction::CallStoreGlobalVar |
+                    &Instruction::CallStreamProperty |
+                    &Instruction::CallSetStreamPosition |
+                    &Instruction::CallInferenceLevel |
+                    &Instruction::CallCleanUpBlock |
+                    &Instruction::CallFail |
+                    &Instruction::CallGetBall |
+                    &Instruction::CallGetCurrentBlock |
+                    &Instruction::CallGetCutPoint |
+                    &Instruction::CallGetDoubleQuotes |
+                    &Instruction::CallInstallNewBlock |
+                    &Instruction::CallMaybe |
+                    &Instruction::CallCpuNow |
+                    &Instruction::CallDeterministicLengthRundown |
+                    &Instruction::CallHttpOpen |
+                    &Instruction::CallHttpListen |
+                    &Instruction::CallHttpAccept |
+                    &Instruction::CallHttpAnswer |
+                           &Instruction::CallLoadForeignLib |
+                           &Instruction::CallForeignCall |
+                           &Instruction::CallDefineForeignStruct |
+                    &Instruction::CallPredicateDefined |
+                    &Instruction::CallStripModule |
+                    &Instruction::CallCurrentTime |
+                    &Instruction::CallQuotedToken |
+                    &Instruction::CallReadTermFromChars |
+                    &Instruction::CallResetBlock |
+                    &Instruction::CallReturnFromVerifyAttr |
+                    &Instruction::CallSetBall |
+                    &Instruction::CallPushBallStack |
+                    &Instruction::CallPopBallStack |
+                    &Instruction::CallPopFromBallStack |
                     &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::CallInlinedInstructions(_) |
-                    &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(_) => {
+                    &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::CallInlinedInstructions |
+                    &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::ExecuteFileCopy(_) |
-                    &Instruction::ExecuteWorkingDirectory(_) |
-                    &Instruction::ExecuteDeleteDirectory(_) |
-                    &Instruction::ExecutePathCanonical(_) |
-                    &Instruction::ExecuteFileTime(_) |
+                    &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::ExecuteFileCopy |
+                    &Instruction::ExecuteWorkingDirectory |
+                    &Instruction::ExecuteDeleteDirectory |
+                    &Instruction::ExecutePathCanonical |
+                    &Instruction::ExecuteFileTime |
                     &Instruction::ExecuteDynamicModuleResolution(..) |
                     &Instruction::ExecutePrepareCallClause(..) |
-                    &Instruction::ExecuteCompileInlineOrExpandedGoal(..) |
-                    &Instruction::ExecuteIsExpandedOrInlined(_) |
-                    &Instruction::ExecuteGetClauseP(_) |
-                    &Instruction::ExecuteInvokeClauseAtP(_) |
-                    &Instruction::ExecuteGetFromAttributedVarList(_) |
-                    &Instruction::ExecutePutToAttributedVarList(_) |
-                    &Instruction::ExecuteDeleteFromAttributedVarList(_) |
-                    &Instruction::ExecuteDeleteAllAttributesFromVar(_) |
-                    &Instruction::ExecuteUnattributedVar(_) |
-                    &Instruction::ExecuteGetDBRefs(_) |
-                    &Instruction::ExecuteEnqueueAttributedVar(_) |
-                    &Instruction::ExecuteFetchGlobalVar(_) |
-                    &Instruction::ExecuteFirstStream(_) |
-                    &Instruction::ExecuteFlushOutput(_) |
-                    &Instruction::ExecuteGetByte(_) |
-                    &Instruction::ExecuteGetChar(_) |
-                    &Instruction::ExecuteGetNChars(_) |
-                    &Instruction::ExecuteGetCode(_) |
-                    &Instruction::ExecuteGetSingleChar(_) |
-                    &Instruction::ExecuteTruncateIfNoLiftedHeapGrowthDiff(_) |
-                    &Instruction::ExecuteTruncateIfNoLiftedHeapGrowth(_) |
-                    &Instruction::ExecuteGetAttributedVariableList(_) |
-                    &Instruction::ExecuteGetAttrVarQueueDelimiter(_) |
-                    &Instruction::ExecuteGetAttrVarQueueBeyond(_) |
-                    &Instruction::ExecuteGetBValue(_) |
-                    &Instruction::ExecuteGetContinuationChunk(_) |
-                    &Instruction::ExecuteGetNextOpDBRef(_) |
-                    &Instruction::ExecuteLookupDBRef(_) |
-                    &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::ExecuteFail(_) |
-                    &Instruction::ExecuteGetBall(_) |
-                    &Instruction::ExecuteGetCurrentBlock(_) |
-                    &Instruction::ExecuteGetCutPoint(_) |
-                    &Instruction::ExecuteGetDoubleQuotes(_) |
-                    &Instruction::ExecuteInstallNewBlock(_) |
-                    &Instruction::ExecuteMaybe(_) |
-                    &Instruction::ExecuteCpuNow(_) |
-                    &Instruction::ExecuteDeterministicLengthRundown(_) |
-                    &Instruction::ExecuteHttpOpen(_) |
-                    &Instruction::ExecuteHttpListen(_) |
-                    &Instruction::ExecuteHttpAccept(_) |
-                    &Instruction::ExecuteHttpAnswer(_) |
-                           &Instruction::ExecuteLoadForeignLib(_) |
-                           &Instruction::ExecuteForeignCall(_) |
-                           &Instruction::ExecuteDefineForeignStruct(_) |
-                    &Instruction::ExecutePredicateDefined(_) |
-                    &Instruction::ExecuteStripModule(_) |
-                    &Instruction::ExecuteCurrentTime(_) |
-                    &Instruction::ExecuteQuotedToken(_) |
-                    &Instruction::ExecuteReadTermFromChars(_) |
-                    &Instruction::ExecuteResetBlock(_) |
-                    &Instruction::ExecuteReturnFromVerifyAttr(_) |
-                    &Instruction::ExecuteSetBall(_) |
-                    &Instruction::ExecutePushBallStack(_) |
-                    &Instruction::ExecutePopBallStack(_) |
-                    &Instruction::ExecutePopFromBallStack(_) |
-                    &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::ExecuteInlinedInstructions(_) |
-                    &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(_) => {
+                    &Instruction::ExecuteCompileInlineOrExpandedGoal |
+                    &Instruction::ExecuteIsExpandedOrInlined |
+                    &Instruction::ExecuteGetClauseP |
+                    &Instruction::ExecuteInvokeClauseAtP |
+                    &Instruction::ExecuteGetFromAttributedVarList |
+                    &Instruction::ExecutePutToAttributedVarList |
+                    &Instruction::ExecuteDeleteFromAttributedVarList |
+                    &Instruction::ExecuteDeleteAllAttributesFromVar |
+                    &Instruction::ExecuteUnattributedVar |
+                    &Instruction::ExecuteGetDBRefs |
+                    &Instruction::ExecuteFetchGlobalVar |
+                    &Instruction::ExecuteFirstStream |
+                    &Instruction::ExecuteFlushOutput |
+                    &Instruction::ExecuteGetByte |
+                    &Instruction::ExecuteGetChar |
+                    &Instruction::ExecuteGetNChars |
+                    &Instruction::ExecuteGetCode |
+                    &Instruction::ExecuteGetSingleChar |
+                    &Instruction::ExecuteTruncateIfNoLiftedHeapGrowthDiff |
+                    &Instruction::ExecuteTruncateIfNoLiftedHeapGrowth |
+                    &Instruction::ExecuteGetAttributedVariableList |
+                    &Instruction::ExecuteGetAttrVarQueueDelimiter |
+                    &Instruction::ExecuteGetAttrVarQueueBeyond |
+                    &Instruction::ExecuteGetBValue |
+                    &Instruction::ExecuteGetContinuationChunk |
+                    &Instruction::ExecuteGetNextOpDBRef |
+                    &Instruction::ExecuteLookupDBRef |
+                    &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::ExecuteFail |
+                    &Instruction::ExecuteGetBall |
+                    &Instruction::ExecuteGetCurrentBlock |
+                    &Instruction::ExecuteGetCutPoint |
+                    &Instruction::ExecuteGetDoubleQuotes |
+                    &Instruction::ExecuteInstallNewBlock |
+                    &Instruction::ExecuteMaybe |
+                    &Instruction::ExecuteCpuNow |
+                    &Instruction::ExecuteDeterministicLengthRundown |
+                    &Instruction::ExecuteHttpOpen |
+                    &Instruction::ExecuteHttpListen |
+                    &Instruction::ExecuteHttpAccept |
+                    &Instruction::ExecuteHttpAnswer |
+                           &Instruction::ExecuteLoadForeignLib |
+                           &Instruction::ExecuteForeignCall |
+                           &Instruction::ExecuteDefineForeignStruct |
+                    &Instruction::ExecutePredicateDefined |
+                    &Instruction::ExecuteStripModule |
+                    &Instruction::ExecuteCurrentTime |
+                    &Instruction::ExecuteQuotedToken |
+                    &Instruction::ExecuteReadTermFromChars |
+                    &Instruction::ExecuteResetBlock |
+                    &Instruction::ExecuteReturnFromVerifyAttr |
+                    &Instruction::ExecuteSetBall |
+                    &Instruction::ExecutePushBallStack |
+                    &Instruction::ExecutePopBallStack |
+                    &Instruction::ExecutePopFromBallStack |
+                    &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::ExecuteInlinedInstructions |
+                    &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)])
                     }
@@ -2044,12 +2053,9 @@ fn generate_instruction_preface() -> TokenStream {
                     &Instruction::Deallocate => {
                         functor!(atom!("deallocate"))
                     }
-                    &Instruction::JmpByCall(_, offset, ..) => {
+                    &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)])
                     }
@@ -2244,6 +2250,7 @@ pub fn generate_instructions_rs() -> TokenStream {
     let mut clause_type_to_instr_arms = vec![];
     let mut clause_type_name_arms = vec![];
     let mut is_inbuilt_arms = vec![];
+    let mut is_inlined_arms = vec![];
 
     for (name, arity, variant) in instr_data.compare_number_variants {
         let ident = variant.ident.clone();
@@ -2295,7 +2302,7 @@ pub fn generate_instructions_rs() -> TokenStream {
             quote! {
                 ClauseType::Inlined(
                     InlinedClauseType::CompareNumber(CompareNumber::#ident(#(#placeholder_ids),*))
-                ) => Instruction::#instr_ident(#(#placeholder_ids),*, 0)
+                ) => Instruction::#instr_ident(#(*#placeholder_ids),*)
             }
         );
 
@@ -2330,7 +2337,7 @@ pub fn generate_instructions_rs() -> TokenStream {
             quote! {
                 ClauseType::BuiltIn(
                     BuiltInClauseType::CompareTerm(CompareTerm::#ident)
-                ) => Instruction::#instr_ident(0)
+                ) => Instruction::#instr_ident
             }
         );
 
@@ -2391,13 +2398,13 @@ pub fn generate_instructions_rs() -> TokenStream {
             quote! {
                 ClauseType::BuiltIn(
                     BuiltInClauseType::#ident(#(#placeholder_ids),*)
-                ) => Instruction::#instr_ident(#(#placeholder_ids),*,0)
+                ) => Instruction::#instr_ident(#(*#placeholder_ids),*)
             }
         } else {
             quote! {
                 ClauseType::BuiltIn(
                     BuiltInClauseType::#ident
-                ) => Instruction::#instr_ident(0)
+                ) => Instruction::#instr_ident
             }
         });
 
@@ -2462,7 +2469,7 @@ pub fn generate_instructions_rs() -> TokenStream {
             quote! {
                 ClauseType::Inlined(
                     InlinedClauseType::#ident(#(#placeholder_ids),*)
-                ) => Instruction::#instr_ident(#(#placeholder_ids),*,0)
+                ) => Instruction::#instr_ident(*#(#placeholder_ids),*)
             }
         );
 
@@ -2471,6 +2478,12 @@ pub fn generate_instructions_rs() -> TokenStream {
                 (atom!(#name), #arity) => true
             }
         );
+
+        is_inlined_arms.push(
+            quote! {
+                (atom!(#name), #arity) => true
+            }
+        );
     }
 
     for (name, arity, variant) in instr_data.system_clause_type_variants {
@@ -2552,13 +2565,13 @@ pub fn generate_instructions_rs() -> TokenStream {
             quote! {
                 ClauseType::System(
                     SystemClauseType::#ident(#(#placeholder_ids),*)
-                ) => Instruction::#instr_ident(#(#placeholder_ids),*,0)
+                ) => Instruction::#instr_ident(#(*#placeholder_ids),*)
             }
         } else {
             quote! {
                 ClauseType::System(
                     SystemClauseType::#ident
-                ) => Instruction::#instr_ident(0)
+                ) => Instruction::#instr_ident
             }
         });
 
@@ -2629,13 +2642,13 @@ pub fn generate_instructions_rs() -> TokenStream {
             quote! {
                 ClauseType::System(SystemClauseType::REPL(
                     REPLCodePtr::#ident(#(#placeholder_ids),*)
-                )) => Instruction::#instr_ident(#(#placeholder_ids),*,0)
+                )) => Instruction::#instr_ident(#(*#placeholder_ids),*)
             }
         } else {
             quote! {
                 ClauseType::System(SystemClauseType::REPL(
                     REPLCodePtr::#ident
-                )) => Instruction::#instr_ident(0)
+                )) => Instruction::#instr_ident
             }
         });
 
@@ -2655,7 +2668,7 @@ pub fn generate_instructions_rs() -> TokenStream {
             });
 
             clause_type_to_instr_arms.push(quote! {
-                ClauseType::Named(arity, name, idx) => Instruction::CallNamed(arity, name, idx, 0)
+                ClauseType::Named(arity, name, idx) => Instruction::CallNamed(*arity, *name, *idx)
             });
 
             clause_type_name_arms.push(quote! {
@@ -2706,11 +2719,11 @@ pub fn generate_instructions_rs() -> TokenStream {
         clause_type_to_instr_arms.push(if !variant_fields.is_empty() {
             quote! {
                 ClauseType::#ident(#(#placeholder_ids),*) =>
-                    Instruction::#ident(#(#placeholder_ids),*,0)
+                    Instruction::#ident(#(*#placeholder_ids),*)
             }
         } else {
             quote! {
-                ClauseType::#ident => Instruction::#ident(0)
+                ClauseType::#ident => Instruction::#ident
             }
         });
 
@@ -2767,11 +2780,6 @@ pub fn generate_instructions_rs() -> TokenStream {
                             Instruction::#execute_ident(#(#placeholder_ids),*)
                     }
                 })
-            } else if variant_string == "JmpByCall" {
-                Some(quote! {
-                    Instruction::JmpByCall(#(#placeholder_ids),*) =>
-                        Instruction::JmpByExecute(#(#placeholder_ids),*)
-                })
             } else {
                 None
             }
@@ -2835,16 +2843,23 @@ pub fn generate_instructions_rs() -> TokenStream {
                 let enum_arity = if let Fields::Unnamed(fields) = &variant.fields {
                     fields.unnamed.len()
                 } else {
-                    unreachable!()
+                    0
                 };
 
                 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),*)
+                Some(if enum_arity == 0 {
+                    quote! {
+                        Instruction::#variant_ident =>
+                            Instruction::#def_variant_ident
+                    }
+                } else {
+                    quote! {
+                        Instruction::#variant_ident(#(#placeholder_ids),*) =>
+                            Instruction::#def_variant_ident(#(#placeholder_ids),*)
+                    }
                 })
             } else {
                 None
@@ -2852,7 +2867,7 @@ pub fn generate_instructions_rs() -> TokenStream {
         })
         .collect();
 
-    let perm_vars_mut_arms: Vec<_> = instr_data.instr_variants
+    let control_flow_arms: Vec<_> = instr_data.instr_variants
         .iter()
         .cloned()
         .filter_map(|(_, _, _, variant)| {
@@ -2860,46 +2875,26 @@ pub fn generate_instructions_rs() -> TokenStream {
                 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();
+            let variant_ident = variant.ident.clone();
 
-            Some(if enum_arity == 1 {
+            Some(if enum_arity == 0 {
                 quote! {
-                    Instruction::#variant_ident(ref mut perm_vars) => Some(perm_vars)
+                    Instruction::#variant_ident => true
                 }
             } else {
                 quote! {
-                    Instruction::#variant_ident(#(#placeholder_ids),*, ref mut perm_vars) =>
-                        Some(perm_vars)
+                    Instruction::#variant_ident(..) => true
                 }
             })
         })
         .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.
@@ -2913,27 +2908,59 @@ pub fn generate_instructions_rs() -> TokenStream {
             };
 
             Some(if variant_string.starts_with("Execute") {
-                quote! {
-                    (#name, execute, $($args:expr),*) => {
-                        Instruction::#variant_ident($($args),*)
+                if arity == 0 {
+                    quote! {
+                        (#name, execute) => {
+                            Instruction::#variant_ident
+                        }
+                    }
+                } else {
+                    quote! {
+                        (#name, execute, $($args:expr),*) => {
+                            Instruction::#variant_ident($($args),*)
+                        }
                     }
                 }
             } else if variant_string.starts_with("Call") {
-                quote! {
-                    (#name, $($args:expr),*) => {
-                        Instruction::#variant_ident($($args),*)
+                if arity == 0 {
+                    quote! {
+                        (#name) => {
+                            Instruction::#variant_ident
+                        }
+                    }
+                } else {
+                    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),*)
+                if arity == 0 {
+                    quote! {
+                        (#name, execute, default) => {
+                            Instruction::#variant_ident
+                        }
+                    }
+                } else {
+                    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),*)
+                if arity == 0 {
+                    quote! {
+                        (#name, default) => {
+                            Instruction::#variant_ident
+                        }
+                    }
+                } else {
+                    quote! {
+                        (#name, default, $($args:expr),*) => {
+                            Instruction::#variant_ident($($args),*)
+                        }
                     }
                 }
             } else {
@@ -3061,7 +3088,7 @@ pub fn generate_instructions_rs() -> TokenStream {
                 }
             }
 
-            pub fn to_instr(self) -> Instruction {
+            pub fn to_instr(&self) -> Instruction {
                 match self {
                     #(
                         #clause_type_to_instr_arms,
@@ -3085,6 +3112,15 @@ pub fn generate_instructions_rs() -> TokenStream {
                     )*
                 }
             }
+
+            pub fn is_inlined(name: Atom, arity: usize) -> bool {
+                match (name, arity) {
+                    #(
+                        #is_inlined_arms,
+                    )*
+                    _ => false,
+                }
+            }
         }
 
         #[derive(Clone, Debug)]
@@ -3130,15 +3166,6 @@ pub fn generate_instructions_rs() -> TokenStream {
                 }
             }
 
-            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(_) |
@@ -3201,41 +3228,6 @@ fn is_jmp(id: &Ident) -> bool {
 }
 
 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();
 
index 50e9c7c330377de4dfba5e96889c427bd3a4a7c5..f689a802cc5cf0bd2095cdf3a400f727a280767b 100644 (file)
@@ -1,10 +1,7 @@
 use crate::parser::ast::*;
-use crate::temp_v;
 
-use crate::fixtures::*;
 use crate::forms::*;
 use crate::instructions::*;
-use crate::machine::machine_indices::*;
 use crate::targets::*;
 
 use std::cell::Cell;
@@ -16,7 +13,7 @@ pub(crate) trait Allocator {
         &mut self,
         lvl: Level,
         context: GenContext,
-        code: &mut Code,
+        code: &mut CodeDeque,
     );
 
     fn mark_non_var<'a, Target: CompilationTarget<'a>>(
@@ -24,40 +21,44 @@ pub(crate) trait Allocator {
         lvl: Level,
         context: GenContext,
         cell: &'a Cell<RegType>,
-        code: &mut Code,
+        code: &mut CodeDeque,
     );
 
     fn mark_reserved_var<'a, Target: CompilationTarget<'a>>(
         &mut self,
-        var_name: Var,
+        var_num: usize,
         lvl: Level,
         cell: &'a Cell<VarReg>,
         term_loc: GenContext,
-        code: &mut Code,
+        code: &mut CodeDeque,
         r: RegType,
         is_new_var: bool,
     );
 
+    fn mark_cut_var(&mut self, var_num: usize, chunk_num: usize) -> RegType;
+
     fn mark_var<'a, Target: CompilationTarget<'a>>(
         &mut self,
-        var_name: Var,
+        var_num: usize,
         lvl: Level,
         cell: &'a Cell<VarReg>,
         context: GenContext,
-        code: &mut Code,
+        code: &mut CodeDeque,
     );
 
     fn reset(&mut self);
-    fn reset_contents(&mut self) {}
     fn reset_arg(&mut self, arg_num: usize);
     fn reset_at_head(&mut self, args: &Vec<Term>);
+    fn reset_contents(&mut self);
 
     fn advance_arg(&mut self);
 
+    /*
     fn bindings(&self) -> &AllocVarDict;
     fn bindings_mut(&mut self) -> &mut AllocVarDict;
-
     fn take_bindings(self) -> AllocVarDict;
+    */
+
     fn max_reg_allocated(&self) -> usize;
 
     // TODO: wha.. why?? grrr. it drains the VarStatus data from vs (which it owns!)
@@ -87,21 +88,4 @@ pub(crate) trait Allocator {
         perm_vs
     }
     */
-
-    fn get(&self, var: Var) -> RegType {
-        self.bindings()
-            .get(&var)
-            .map_or(temp_v!(0), |v| v.as_reg_type())
-    }
-
-    fn is_unbound(&self, var: Var) -> bool {
-        self.get(var).reg_num() == 0
-    }
-
-    fn record_register(&mut self, var: Var, r: RegType) {
-        match self.bindings_mut().get_mut(&var).unwrap() {
-            &mut VarAlloc::Temp(_, ref mut s, _) => *s = r.reg_num(),
-            &mut VarAlloc::Perm(ref mut s) => *s = r.reg_num(),
-        }
-    }
 }
index 94974a5104f1f3546a009fb887e065ea6b37fb1f..0fbd91d5cbad4cbe6a467dec9cb32a450ccea63c 100644 (file)
@@ -52,7 +52,7 @@ pub(crate) struct ArithInstructionIterator<'a> {
     state_stack: Vec<TermIterState<'a>>,
 }
 
-pub(crate) type ArithCont = (Code, Option<ArithmeticTerm>);
+pub(crate) type ArithCont = (CodeDeque, Option<ArithmeticTerm>);
 
 impl<'a> ArithInstructionIterator<'a> {
     fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
@@ -73,7 +73,7 @@ impl<'a> ArithInstructionIterator<'a> {
                     2,
                 ))
             }
-            Term::Var(cell, var) => TermIterState::Var(Level::Shallow, cell, VarPtr::from(var)),
+            Term::Var(cell, var_ptr) => TermIterState::Var(Level::Shallow, cell, var_ptr.clone()),
         };
 
         Ok(ArithInstructionIterator {
@@ -86,7 +86,7 @@ impl<'a> ArithInstructionIterator<'a> {
 pub(crate) enum ArithTermRef<'a> {
     Literal(&'a Literal),
     Op(Atom, usize), // name, arity.
-    Var(Level, &'a Cell<VarReg>, Var),
+    Var(Level, &'a Cell<VarReg>, VarPtr),
 }
 
 impl<'a> Iterator for ArithInstructionIterator<'a> {
@@ -114,8 +114,8 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
                     }
                 }
                 TermIterState::Literal(_, _, c) => return Some(Ok(ArithTermRef::Literal(c))),
-                TermIterState::Var(lvl, cell, var_ref) => {
-                    return Some(Ok(ArithTermRef::Var(lvl, cell, Var::from(var_ref))));
+                TermIterState::Var(lvl, cell, var_ptr) => {
+                    return Some(Ok(ArithTermRef::Var(lvl, cell, var_ptr)));
                 }
                 _ => {
                     return Some(Err(ArithmeticError::NonEvaluableFunctor(
@@ -307,43 +307,48 @@ impl<'a> ArithmeticEvaluator<'a> {
         term_loc: GenContext,
         arg: usize,
     ) -> Result<ArithCont, ArithmeticError> {
-        let mut code = vec![];
+        let mut code = CodeDeque::new();
         let mut iter = src.iter()?;
 
         while let Some(term_ref) = iter.next() {
             match term_ref? {
                 ArithTermRef::Literal(c) => push_literal(&mut self.interm, c)?,
                 ArithTermRef::Var(lvl, cell, name) => {
+                    let var_num = name.to_var_num().unwrap();
+
                     let r = if lvl == Level::Shallow {
                         self.marker.mark_non_callable(
-                            name,
+                            var_num,
                             arg,
                             term_loc,
                             cell,
                             &mut code,
                         )
                     } else if term_loc.is_last() || cell.get().norm().reg_num() == 0 {
-                        if let Some(r) = self.marker.get_binding(&name) {
-                            r
-                        } else {
+                        let r = self.marker.get_binding(var_num);
+
+                        if r.reg_num() == 0 {
                             self.marker.mark_var::<QueryInstruction>(
-                                name.clone(),
+                                var_num,
                                 lvl,
                                 cell,
                                 term_loc,
                                 &mut code,
                             );
-
-                            self.marker.get_binding(&name).unwrap()
+                        } else {
+                            self.marker.increment_running_count(var_num);
                         }
+
+                        r
                     } else {
+                        self.marker.increment_running_count(var_num);
                         cell.get().norm()
                     };
 
                     self.interm.push(ArithmeticTerm::Reg(r));
                 }
                 ArithTermRef::Op(name, arity) => {
-                    code.push(self.instr_from_clause(name, arity)?);
+                    code.push_back(self.instr_from_clause(name, arity)?);
                 }
             }
         }
index e7c6e2ac9198608cc41a361e48d4f9215809760d..794ec65b2d98adcd6cbc188841f50415158212dd 100644 (file)
@@ -1,10 +1,9 @@
 use crate::atom_table::*;
 use crate::parser::ast::*;
-use crate::{perm_v, temp_v};
+use crate::temp_v;
 use crate::allocator::*;
 use crate::arithmetic::*;
 use crate::debray_allocator::*;
-use crate::fixtures::*;
 use crate::forms::*;
 use crate::indexing::*;
 use crate::instructions::*;
@@ -13,39 +12,139 @@ use crate::targets::*;
 use crate::types::*;
 
 use crate::instr;
+use crate::machine::disjuncts::*;
 use crate::machine::machine_errors::*;
 
-use indexmap::{IndexMap, IndexSet};
+use fxhash::FxBuildHasher;
+use indexmap::IndexSet;
 
 use std::cell::Cell;
 use std::collections::VecDeque;
 
 #[derive(Debug)]
-pub(crate) struct ConjunctInfo {
-    pub(crate) perm_vs: VariableFixtures,
-    pub(crate) num_of_chunks: usize,
-    pub(crate) has_deep_cut: bool,
+pub struct BranchCodeStack {
+    pub stack: Vec<Vec<CodeDeque>>,
 }
 
-impl ConjunctInfo {
-    fn new(perm_vs: VariableFixtures, num_of_chunks: usize, has_deep_cut: bool) -> Self {
-        ConjunctInfo {
-            perm_vs,
-            num_of_chunks,
-            has_deep_cut,
+pub type SubsumedBranchHits = IndexSet<usize, FxBuildHasher>;
+
+impl BranchCodeStack {
+    fn new() -> Self {
+        Self { stack: vec![] }
+    }
+
+    fn add_new_branch_stack(&mut self) {
+        self.stack.push(vec![]);
+    }
+
+    fn add_new_branch(&mut self) {
+        if self.stack.is_empty() {
+            self.add_new_branch_stack();
+        }
+
+        if let Some(branches) = self.stack.last_mut() {
+            branches.push(CodeDeque::new());
         }
     }
 
-    fn allocates(&self) -> bool {
-        self.perm_vs.size() > 0 || self.num_of_chunks > 1 || self.has_deep_cut
+    fn code<'a>(&'a mut self, default_code: &'a mut CodeDeque) -> &'a mut CodeDeque {
+        self.stack.last_mut()
+            .and_then(|stack| stack.last_mut())
+            .unwrap_or(default_code)
+    }
+
+    fn push_missing_vars(&mut self, depth: usize, marker: &mut DebrayAllocator) -> SubsumedBranchHits {
+        let mut subsumed_hits = SubsumedBranchHits::with_hasher(FxBuildHasher::default());
+
+        for idx in (self.stack.len() - depth .. self.stack.len()).rev() {
+            let branch = &mut marker.branch_stack[idx];
+            let branch_hits = &branch.hits;
+
+            for (&var_num, branches) in branch_hits.iter() {
+                let record = &marker.var_data.records[var_num];
+
+                if record.running_count < record.num_occurrences {
+                    if !branches.all() {
+                        branch.deep_safety.insert(var_num);
+                        branch.shallow_safety.insert(var_num);
+
+                        let r = record.allocation.as_reg_type();
+
+                        // iterate over unset bits.
+                        for branch_idx in branches.iter_zeros() {
+                            if branch_idx + 1 == branches.len() && idx + 1 != self.stack.len() {
+                                break;
+                            }
+
+                            self.stack[idx][branch_idx].push_back(instr!("put_variable", r, 0));
+                        }
+                    }
+
+                    subsumed_hits.insert(var_num);
+                }
+            }
+        }
+
+        subsumed_hits
     }
 
-    fn perm_vars(&self) -> usize {
-        self.perm_vs.size() + self.perm_var_offset()
+    fn push_jump_instrs(&mut self, depth: usize) {
+        // add 2 in each arm length to compensate for each jump
+        // instruction and each branch instruction not yet added.
+        let mut jump_span: usize = self.stack[self.stack.len() - depth ..]
+            .iter()
+            .map(|branch| branch.iter().map(|code| code.len() + 2).sum::<usize>())
+            .sum();
+
+        jump_span -= depth;
+
+        for idx in self.stack.len() - depth .. self.stack.len() {
+            let inner_len = self.stack[idx].len();
+
+            for (inner_idx, code) in self.stack[idx].iter_mut().enumerate() {
+                if inner_idx + 1 == inner_len {
+                    jump_span -= code.len() + 1; // = jump_span.saturating_sub(code.len() + 1);
+                } else {
+                    jump_span -= code.len() + 1;
+                    code.push_back(instr!("jmp_by_call", jump_span as usize));
+
+                    // saturate at 0 if underflow happens, which only
+                    // happens when jump_span is no longer needed
+                    // anyway. still, we don't want to panic at
+                    // underflow.
+                    jump_span -= 1;
+                }
+            }
+        }
+
+        // eliminate terminating jump instruction in last arm of last
+        // branch.
+        // self.stack.last_mut()
+        //     .and_then(|branch| branch.last_mut())
+        //     .map(|code| code.pop_back());
     }
 
-    fn perm_var_offset(&self) -> usize {
-        self.has_deep_cut as usize
+    fn pop_branch(&mut self, depth: usize, settings: CodeGenSettings) -> CodeDeque {
+        let mut combined_code = CodeDeque::new();
+
+        for mut branch_arm in self.stack.drain(self.stack.len() - depth ..).rev() {
+            let num_branch_arms = branch_arm.len();
+            branch_arm.last_mut().map(|code| code.extend(combined_code.drain(..)));
+
+            for (idx, code) in branch_arm.into_iter().enumerate() {
+                combined_code.push_back(if idx == 0 {
+                    Instruction::TryMeElse(code.len() + 1)
+                } else if idx + 1 < num_branch_arms {
+                    settings.retry_me_else(code.len() + 1)
+                } else {
+                    settings.trust_me()
+                });
+
+                combined_code.extend(code.into_iter());
+            }
+        }
+
+        combined_code
     }
 }
 
@@ -168,53 +267,49 @@ impl CodeGenSettings {
 pub(crate) struct CodeGenerator<'a> {
     pub(crate) atom_tbl: &'a mut AtomTable,
     marker: DebrayAllocator,
-    pub(crate) var_count: IndexMap<Var, usize>,
     settings: CodeGenSettings,
     pub(crate) skeleton: PredicateSkeleton,
-    pub(crate) jmp_by_locs: Vec<usize>,
-    global_jmp_by_locs_offset: usize,
 }
 
 impl DebrayAllocator {
     fn mark_var_in_non_callable(
         &mut self,
-        name: Var,
+        var_num: usize,
         term_loc: GenContext,
         vr: &Cell<VarReg>,
-        code: &mut Code,
+        code: &mut CodeDeque,
     ) -> RegType {
-        self.mark_var::<QueryInstruction>(name, Level::Shallow, vr, term_loc, code);
-        vr.get().norm()
-    }
+        self.mark_var::<QueryInstruction>(
+            var_num,
+            Level::Shallow,
+            vr,
+            term_loc,
+            code,
+        );
 
-    #[inline(always)]
-    pub(crate) fn get_binding(&self, name: &Var) -> Option<RegType> {
-        match self.bindings().get(name) {
-            Some(&VarAlloc::Temp(_, t, _)) if t != 0 => Some(RegType::Temp(t)),
-            Some(&VarAlloc::Perm(p)) if p != 0 => Some(RegType::Perm(p)),
-            _ => None,
-        }
+        vr.get().norm()
     }
 
     pub(crate) fn mark_non_callable(
         &mut self,
-        name: Var,
+        var_num: usize,
         arg: usize,
         term_loc: GenContext,
         vr: &Cell<VarReg>,
-        code: &mut Code,
+        code: &mut CodeDeque,
     ) -> RegType {
-        match self.get_binding(&name) {
-            Some(RegType::Temp(t)) => RegType::Temp(t),
-            Some(RegType::Perm(p)) => {
+        match self.get_binding(var_num) {
+            RegType::Temp(t) if t != 0 => RegType::Temp(t),
+            RegType::Perm(p) if p != 0 => {
                 if let GenContext::Last(_) = term_loc {
-                    self.mark_var_in_non_callable(name.clone(), term_loc, vr, code);
+                    self.mark_var_in_non_callable(var_num, term_loc, vr, code);
                     temp_v!(arg)
                 } else {
+                    self.increment_running_count(var_num);
                     RegType::Perm(p)
                 }
             }
-            None => self.mark_var_in_non_callable(name, term_loc, vr, code),
+            _ => self.mark_var_in_non_callable(var_num, term_loc, vr, code),
         }
     }
 }
@@ -280,50 +375,34 @@ impl<'b> CodeGenerator<'b> {
         CodeGenerator {
             atom_tbl,
             marker: DebrayAllocator::new(),
-            var_count: IndexMap::new(),
             settings,
             skeleton: PredicateSkeleton::new(),
-            jmp_by_locs: vec![],
-            global_jmp_by_locs_offset: 0,
-        }
-    }
-
-    fn update_var_count<'a, Iter: Iterator<Item = TermRef<'a>>>(&mut self, iter: Iter) {
-        for term in iter {
-            if let TermRef::Var(_, _, var) = term {
-                let entry = self.var_count.entry(var).or_insert(0);
-                *entry += 1;
-            }
         }
     }
 
-    fn get_var_count(&self, var: &Var) -> usize {
-        *self.var_count.get(var).unwrap()
-    }
-
-    fn add_or_increment_void_instr<'a, Target>(target: &mut Code)
+    fn add_or_increment_void_instr<'a, Target>(target: &mut CodeDeque)
     where
         Target: crate::targets::CompilationTarget<'a>,
     {
-        if let Some(ref mut instr) = target.last_mut() {
+        if let Some(ref mut instr) = target.back_mut() {
             if Target::is_void_instr(&*instr) {
                 Target::incr_void_instr(instr);
                 return;
             }
         }
 
-        target.push(Target::to_void(1));
+        target.push_back(Target::to_void(1));
     }
 
     fn deep_var_instr<'a, Target: crate::targets::CompilationTarget<'a>>(
         &mut self,
         cell: &'a Cell<VarReg>,
-        var: &Var,
+        var_num: usize,
         term_loc: GenContext,
-        target: &mut Code,
+        target: &mut CodeDeque,
     ) {
-        if self.get_var_count(var.as_ref()) > 1 {
-            self.marker.mark_var::<Target>(var.clone(), Level::Deep, cell, term_loc, target);
+        if self.marker.var_data.records[var_num].num_occurrences > 1 {
+            self.marker.mark_var::<Target>(var_num, Level::Deep, cell, term_loc, target);
         } else {
             Self::add_or_increment_void_instr::<Target>(target);
         }
@@ -333,7 +412,7 @@ impl<'b> CodeGenerator<'b> {
         &mut self,
         subterm: &'a Term,
         term_loc: GenContext,
-        target: &mut Code,
+        target: &mut CodeDeque,
     ) {
         match subterm {
             &Term::AnonVar => {
@@ -344,13 +423,13 @@ impl<'b> CodeGenerator<'b> {
             Term::PartialString(ref cell, ..) |
             Term::CompleteString(ref cell, ..) => {
                 self.marker.mark_non_var::<Target>(Level::Deep, term_loc, cell, target);
-                target.push(Target::clause_arg_to_instr(cell.get()));
+                target.push_back(Target::clause_arg_to_instr(cell.get()));
             }
             &Term::Literal(_, ref constant) => {
-                target.push(Target::constant_subterm(constant.clone()));
+                target.push_back(Target::constant_subterm(constant.clone()));
             }
-            &Term::Var(ref cell, ref var) => {
-                self.deep_var_instr::<Target>(cell, var, term_loc, target);
+            &Term::Var(ref cell, ref var_ptr) => {
+                self.deep_var_instr::<Target>(cell, var_ptr.to_var_num().unwrap(), term_loc, target);
             }
         };
     }
@@ -359,13 +438,13 @@ impl<'b> CodeGenerator<'b> {
         &mut self,
         iter: Iter,
         term_loc: GenContext,
-    ) -> Code
+    ) -> CodeDeque
     where
         Target: crate::targets::CompilationTarget<'a>,
         Iter: Iterator<Item = TermRef<'a>>,
         CodeGenerator<'b>: AddToFreeList<'a, Target>
     {
-        let mut target: Code = Vec::new();
+        let mut target = CodeDeque::new();
 
         for term in iter {
             match term {
@@ -378,11 +457,11 @@ impl<'b> CodeGenerator<'b> {
                 }
                 TermRef::Clause(lvl, cell, name, terms) => {
                     self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
-                    target.push(Target::to_structure(name, terms.len(), cell.get()));
+                    target.push_back(Target::to_structure(name, terms.len(), cell.get()));
 
                     <CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(self, cell.get());
 
-                    if let Some(instr) = target.last_mut() {
+                    if let Some(instr) = target.back_mut() {
                         if let Some(term) = terms.last() {
                             trim_structure_by_last_arg(instr, term);
                         }
@@ -398,7 +477,7 @@ impl<'b> CodeGenerator<'b> {
                 }
                 TermRef::Cons(lvl, cell, head, tail) => {
                     self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
-                    target.push(Target::to_list(lvl, cell.get()));
+                    target.push_back(Target::to_list(lvl, cell.get()));
 
                     <CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(self, cell.get());
 
@@ -410,44 +489,31 @@ impl<'b> CodeGenerator<'b> {
                 }
                 TermRef::Literal(lvl @ Level::Shallow, cell, Literal::String(ref string)) => {
                     self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
-                    target.push(Target::to_pstr(lvl, *string, cell.get(), false));
+                    target.push_back(Target::to_pstr(lvl, *string, cell.get(), false));
                 }
                 TermRef::Literal(lvl @ Level::Shallow, cell, constant) => {
                     self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
-                    target.push(Target::to_constant(lvl, *constant, cell.get()));
+                    target.push_back(Target::to_constant(lvl, *constant, cell.get()));
                 }
                 TermRef::PartialString(lvl, cell, string, tail) => {
                     self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
                     let atom = self.atom_tbl.build_with(&string);
 
-                    target.push(Target::to_pstr(lvl, atom, cell.get(), true));
+                    target.push_back(Target::to_pstr(lvl, atom, cell.get(), true));
                     self.subterm_to_instr::<Target>(tail, term_loc, &mut target);
                 }
                 TermRef::CompleteString(lvl, cell, atom) => {
                     self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
-                    target.push(Target::to_pstr(lvl, atom, cell.get(), false));
-                }
-                TermRef::Var(lvl @ Level::Shallow, cell, var) if var.as_str() == Some("!") => {
-                    if self.marker.is_unbound(var.clone()) {
-                        if term_loc != GenContext::Head {
-                            self.marker.mark_reserved_var::<Target>(
-                                var.clone(),
-                                lvl,
-                                cell,
-                                term_loc,
-                                &mut target,
-                                perm_v!(1),
-                                false,
-                            );
-
-                            continue;
-                        }
-                    }
-
-                    self.marker.mark_var::<Target>(var.clone(), lvl, cell, term_loc, &mut target);
+                    target.push_back(Target::to_pstr(lvl, atom, cell.get(), false));
                 }
                 TermRef::Var(lvl @ Level::Shallow, cell, var) => {
-                    self.marker.mark_var::<Target>(var.clone(), lvl, cell, term_loc, &mut target);
+                    self.marker.mark_var::<Target>(
+                        var.to_var_num().unwrap(),
+                        lvl,
+                        cell,
+                        term_loc,
+                        &mut target,
+                    );
                 }
                 _ => {}
             };
@@ -456,82 +522,27 @@ impl<'b> CodeGenerator<'b> {
         target
     }
 
-    /*
-    fn collect_var_data<'a>(&mut self, mut iter: ChunkedIterator<'a>) -> ConjunctInfo<'a> {
-        let mut vs = VariableFixtures::new();
-
-        while let Some((chunk_num, lt_arity, chunked_terms)) = iter.next() {
-            for (i, chunked_term) in chunked_terms.iter().enumerate() {
-                let term_loc = match chunked_term {
-                    &ChunkedTerm::HeadClause(..) => GenContext::Head,
-                    &ChunkedTerm::BodyTerm(_) => {
-                        if i < chunked_terms.len() - 1 {
-                            GenContext::Mid(chunk_num)
-                        } else {
-                            GenContext::Last(chunk_num)
-                        }
-                    }
-                };
-
-                self.update_var_count(chunked_term.post_order_iter());
-                vs.mark_vars_in_chunk(chunked_term.post_order_iter(), lt_arity, term_loc);
-            }
-        }
-
-        let num_of_chunks = iter.chunk_num;
-        let has_deep_cut = iter.encountered_deep_cut();
-
-        vs.populate_restricting_sets();
-        vs.set_perm_vals(has_deep_cut);
-
-        let vs = self.marker.drain_var_data(vs, num_of_chunks);
-        ConjunctInfo::new(vs, num_of_chunks, has_deep_cut)
-    }
-    */
-
-    fn add_conditional_call(&mut self, code: &mut Code, qt: &QueryTerm, pvs: usize) {
-        match qt {
-            &QueryTerm::Jump(ref vars) => {
-                self.jmp_by_locs.push(code.len());
-                code.push(instr!("jmp_by_call", vars.len(), 0, pvs));
-            }
-            &QueryTerm::Clause(_, ref ct, _, CallPolicy::Default) => {
-                code.push(call_clause_by_default!(ct.clone(), pvs));
-            }
-            &QueryTerm::Clause(_, ref ct, _, CallPolicy::Counted) => {
-                code.push(call_clause!(ct.clone(), pvs));
-            }
-            _ => {}
+    fn add_call(&mut self, code: &mut CodeDeque, call_instr: Instruction, call_policy: CallPolicy) {
+        if self.marker.in_tail_position && self.marker.var_data.allocates {
+            code.push_back(instr!("deallocate"));
         }
-    }
-
-    fn lco(code: &mut Code) -> usize {
-        let mut dealloc_index = code.len() - 1;
-        let last_instr = code.pop();
 
-        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()
+        match call_policy {
+            CallPolicy::Default => {
+                if self.marker.in_tail_position {
+                    code.push_back(call_instr.to_execute().to_default());
                 } else {
-                    dealloc_index += 1;
-                    instr
-                });
+                    code.push_back(call_instr.to_default())
+                }
             }
-            Some(instr) => {
-                code.push(instr);
+            CallPolicy::Counted => {
+                if self.marker.in_tail_position {
+                    code.push_back(call_instr.to_execute());
+                } else {
+                    code.push_back(call_instr)
+                }
             }
-            None => {}
         }
-
-        dealloc_index
     }
 
     fn compile_inlined<'a>(
@@ -539,9 +550,9 @@ impl<'b> CodeGenerator<'b> {
         ct: &InlinedClauseType,
         terms: &'a Vec<Term>,
         term_loc: GenContext,
-        code: &mut Code,
+        code: &mut CodeDeque,
     ) -> Result<(), CompilationError> {
-        match ct {
+        let call_instr = match ct {
             &InlinedClauseType::CompareNumber(mut cmp) => {
                 self.marker.reset_arg(2);
 
@@ -559,29 +570,29 @@ impl<'b> CodeGenerator<'b> {
                 let at_1 = at_1.unwrap_or(interm!(1));
                 let at_2 = at_2.unwrap_or(interm!(2));
 
-                code.push(compare_number_instr!(cmp, at_1, at_2));
+                compare_number_instr!(cmp, at_1, at_2)
             }
             &InlinedClauseType::IsAtom(..) => match &terms[0] {
                 &Term::Literal(_, Literal::Char(_)) |
                 &Term::Literal(_, Literal::Atom(atom!("[]"))) |
                 &Term::Literal(_, Literal::Atom(..)) => {
-                    code.push(instr!("$succeed", 0));
+                    instr!("$succeed")
                 }
                 &Term::Var(ref vr, ref name) => {
                     self.marker.reset_arg(1);
 
                     let r = self.marker.mark_non_callable(
-                        name.clone(),
+                        name.to_var_num().unwrap(),
                         1,
                         term_loc,
                         vr,
                         code,
                     );
 
-                    code.push(instr!("atom", r, 0));
+                    instr!("atom", r)
                 }
                 _ => {
-                    code.push(instr!("$fail", 0));
+                    instr!("$fail")
                 }
             },
             &InlinedClauseType::IsAtomic(..) => match &terms[0] {
@@ -590,26 +601,26 @@ impl<'b> CodeGenerator<'b> {
                 &Term::Cons(..) |
                 &Term::PartialString(..) |
                 &Term::CompleteString(..) => {
-                    code.push(instr!("$fail", 0));
+                    instr!("$fail")
                 }
                 &Term::Literal(_, Literal::String(_)) => {
-                    code.push(instr!("$fail", 0));
+                    instr!("$fail")
                 }
                 &Term::Literal(..) => {
-                    code.push(instr!("$succeed", 0));
+                    instr!("$succeed")
                 }
                 &Term::Var(ref vr, ref name) => {
                     self.marker.reset_arg(1);
 
                     let r = self.marker.mark_non_callable(
-                        name.clone(),
+                        name.to_var_num().unwrap(),
                         1,
                         term_loc,
                         vr,
                         code,
                     );
 
-                    code.push(instr!("atomic", r, 0));
+                    instr!("atomic", r)
                 }
             },
             &InlinedClauseType::IsCompound(..) => match &terms[0] {
@@ -618,57 +629,57 @@ impl<'b> CodeGenerator<'b> {
                 &Term::PartialString(..) |
                 &Term::CompleteString(..) |
                 &Term::Literal(_, Literal::String(..)) => {
-                    code.push(instr!("$succeed", 0));
+                    instr!("$succeed")
                 }
                 &Term::Var(ref vr, ref name) => {
                     self.marker.reset_arg(1);
 
                     let r = self.marker.mark_non_callable(
-                        name.clone(),
+                        name.to_var_num().unwrap(),
                         1,
                         term_loc,
                         vr,
                         code,
                     );
 
-                    code.push(instr!("compound", r, 0));
+                    instr!("compound", r)
                 }
                 _ => {
-                    code.push(instr!("$fail", 0));
+                    instr!("$fail")
                 }
             },
             &InlinedClauseType::IsRational(..) => match &terms[0] {
                 &Term::Literal(_, Literal::Rational(_)) => {
-                    code.push(instr!("$succeed", 0));
+                    instr!("$succeed")
                 }
                 &Term::Var(ref vr, ref name) => {
                     self.marker.reset_arg(1);
-                    let r = self.marker.mark_non_callable(name.clone(), 1,  term_loc, vr, code);
-                    code.push(instr!("rational", r, 0));
+                    let r = self.marker.mark_non_callable(name.to_var_num().unwrap(), 1,  term_loc, vr, code);
+                    instr!("rational", r)
                 }
                 _ => {
-                    code.push(instr!("$fail", 0));
+                    instr!("$fail")
                 }
             },
             &InlinedClauseType::IsFloat(..) => match &terms[0] {
                 &Term::Literal(_, Literal::Float(_)) => {
-                    code.push(instr!("$succeed", 0));
+                    instr!("$succeed")
                 }
                 &Term::Var(ref vr, ref name) => {
                     self.marker.reset_arg(1);
 
                     let r = self.marker.mark_non_callable(
-                        name.clone(),
+                        name.to_var_num().unwrap(),
                         1,
                         term_loc,
                         vr,
                         code,
                     );
 
-                    code.push(instr!("float", r, 0));
+                    instr!("float", r)
                 }
                 _ => {
-                    code.push(instr!("$fail", 0));
+                    instr!("$fail")
                 }
             },
             &InlinedClauseType::IsNumber(..) => match &terms[0] {
@@ -676,66 +687,66 @@ impl<'b> CodeGenerator<'b> {
                 &Term::Literal(_, Literal::Rational(_)) |
                 &Term::Literal(_, Literal::Integer(_)) |
                 &Term::Literal(_, Literal::Fixnum(_)) => {
-                    code.push(instr!("$succeed", 0));
+                    instr!("$succeed")
                 }
                 &Term::Var(ref vr, ref name) => {
                     self.marker.reset_arg(1);
 
                     let r = self.marker.mark_non_callable(
-                        name.clone(),
+                        name.to_var_num().unwrap(),
                         1,
                         term_loc,
                         vr,
                         code,
                     );
 
-                    code.push(instr!("number", r, 0));
+                    instr!("number", r)
                 }
                 _ => {
-                    code.push(instr!("$fail", 0));
+                    instr!("$fail")
                 }
             },
             &InlinedClauseType::IsNonVar(..) => match &terms[0] {
                 &Term::AnonVar => {
-                    code.push(instr!("$fail", 0));
+                    instr!("$fail")
                 }
                 &Term::Var(ref vr, ref name) => {
                     self.marker.reset_arg(1);
 
                     let r = self.marker.mark_non_callable(
-                        name.clone(),
+                        name.to_var_num().unwrap(),
                         1,
                         term_loc,
                         vr,
                         code,
                     );
 
-                    code.push(instr!("nonvar", r, 0));
+                    instr!("nonvar", r)
                 }
                 _ => {
-                    code.push(instr!("$succeed", 0));
+                    instr!("$succeed")
                 }
             },
             &InlinedClauseType::IsInteger(..) => match &terms[0] {
                 &Term::Literal(_, Literal::Integer(_)) |
                 &Term::Literal(_, Literal::Fixnum(_)) => {
-                    code.push(instr!("$succeed", 0));
+                    instr!("$succeed")
                 }
                 &Term::Var(ref vr, ref name) => {
                     self.marker.reset_arg(1);
 
                     let r = self.marker.mark_non_callable(
-                        name.clone(),
+                        name.to_var_num().unwrap(),
                         1,
                         term_loc,
                         vr,
                         code,
                     );
 
-                    code.push(instr!("integer", r, 0));
+                    instr!("integer", r)
                 }
                 _ => {
-                    code.push(instr!("$fail", 0));
+                    instr!("$fail")
                 }
             },
             &InlinedClauseType::IsVar(..) => match &terms[0] {
@@ -744,26 +755,29 @@ impl<'b> CodeGenerator<'b> {
                 &Term::Cons(..) |
                 &Term::PartialString(..) |
                 &Term::CompleteString(..) => {
-                    code.push(instr!("$fail", 0));
+                    instr!("$fail")
                 }
                 &Term::AnonVar => {
-                    code.push(instr!("$succeed", 0));
+                    instr!("$succeed")
                 }
                 &Term::Var(ref vr, ref name) => {
                     self.marker.reset_arg(1);
 
                     let r = self.marker.mark_non_callable(
-                        name.clone(),
+                        name.to_var_num().unwrap(),
                         1,
                         term_loc,
                         vr,
                         code,
                     );
 
-                    code.push(instr!("var", r, 0));
+                    instr!("var", r)
                 }
             },
-        }
+        };
+
+        // inlined predicates are never counted, so this overrides nothing.
+        self.add_call(code, call_instr, CallPolicy::Counted);
 
         Ok(())
     }
@@ -782,7 +796,7 @@ impl<'b> CodeGenerator<'b> {
     fn compile_is_call(
         &mut self,
         terms: &Vec<Term>,
-        code: &mut Code,
+        code: &mut CodeDeque,
         term_loc: GenContext,
         call_policy: CallPolicy,
     ) -> Result<(), CompilationError> {
@@ -798,8 +812,11 @@ impl<'b> CodeGenerator<'b> {
 
         let at = match &terms[0] {
             &Term::Var(ref vr, ref name) => {
+                let var_num = name.to_var_num().unwrap();
+                self.marker.mark_temp_to_safe_perm(var_num);
+
                 self.marker.mark_var::<QueryInstruction>(
-                    name.clone(),
+                    var_num,
                     Level::Shallow,
                     vr,
                     term_loc,
@@ -813,208 +830,189 @@ impl<'b> CodeGenerator<'b> {
                               c @ Literal::Rational(_) |
                               c @ Literal::Fixnum(_)) => {
                 let v = HeapCellValue::from(c);
-                code.push(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
+                code.push_back(instr!("put_constant", Level::Shallow, v, temp_v!(1)));
 
                 self.marker.advance_arg();
                 compile_expr!(self, &terms[1], term_loc, code)
             }
             _ => {
-                code.push(instr!("$fail", 0));
+                code.push_back(instr!("$fail"));
                 return Ok(());
             }
         };
 
         let at = at.unwrap_or(interm!(1));
+        self.add_call(code, instr!("is", temp_v!(1), at), call_policy);
 
-        Ok(if let CallPolicy::Default = call_policy {
-            code.push(instr!("is", default, temp_v!(1), at, 0));
-        } else {
-            code.push(instr!("is", temp_v!(1), at, 0));
-        })
-    }
-
-    #[inline]
-    fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &Cell<VarReg>) {
-        let r = self.marker.get(Var::from("!"));
-        cell.set(VarReg::Norm(r));
-        code.push(instr!("$set_cp", cell.get().norm(), 0));
+        Ok(())
     }
 
     fn compile_seq<'a>(
         &mut self,
-        iter: ChunkedIterator<'a>,
-        conjunct_info: &ConjunctInfo,
-        code: &mut Code,
+        clauses: &ChunkedTermVec,
+        code: &mut CodeDeque,
     ) -> Result<(), CompilationError> {
-        for (chunk_num, _, terms) in iter.rule_body_iter() {
-            for (i, term) in terms.iter().enumerate() {
-                let term_loc = if i + 1 < terms.len() {
-                    GenContext::Mid(chunk_num)
-                } else {
-                    GenContext::Last(chunk_num)
-                };
-
-                match *term {
-                    &QueryTerm::UnblockedCut(ref cell) => self.compile_unblocked_cut(code, cell),
-                    &QueryTerm::BlockedCut => code.push(if chunk_num == 0 {
-                        Instruction::NeckCut
-                    } else {
-                        Instruction::Cut(perm_v!(1))
-                    }),
-                    &QueryTerm::Clause(
-                        _,
-                        ClauseType::BuiltIn(BuiltInClauseType::Is(..)),
-                        ref terms,
-                        call_policy,
-                    ) => self.compile_is_call(terms, code, term_loc, call_policy)?,
-                    &QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms, _) => {
-                        self.compile_inlined(ct, terms, term_loc, code)?
-                    }
-                    _ => {
-                        let num_perm_vars = if chunk_num == 0 {
-                            conjunct_info.perm_vars()
+        let mut chunk_num = 0;
+        let mut branch_code_stack = BranchCodeStack::new();
+        let mut clause_iter = ClauseIterator::new(clauses);
+
+        while let Some(clause_item) = clause_iter.next() {
+            match clause_item {
+                ClauseItem::Chunk(chunk) => {
+                    for (idx, term) in chunk.iter().enumerate() {
+                        let term_loc = if idx + 1 < chunk.len() {
+                            GenContext::Mid(chunk_num)
                         } else {
-                            conjunct_info.perm_vs.vars_above_threshold(i + 1)
+                            self.marker.in_tail_position = clause_iter.in_tail_position();
+                            GenContext::Last(chunk_num)
                         };
 
-                        self.compile_query_line(term, term_loc, code, num_perm_vars);
+                        match term {
+                            &QueryTerm::GetLevel(var_num) => {
+                                let code = branch_code_stack.code(code);
+                                let r = self.marker.mark_cut_var(var_num, chunk_num);
+                                code.push_back(instr!("get_level", r));
+                            }
+                            &QueryTerm::GetCutPoint { var_num, prev_b } => {
+                                let code = branch_code_stack.code(code);
+                                let r = self.marker.mark_cut_var(var_num, chunk_num);
+
+                                code.push_back(if prev_b {
+                                    instr!("get_prev_level", r)
+                                } else {
+                                    instr!("get_cut_point", r)
+                                });
+                            }
+                            &QueryTerm::GlobalCut(var_num) => {
+                                let code = branch_code_stack.code(code);
+
+                                if chunk_num == 0 {
+                                    code.push_back(instr!("neck_cut"));
+                                } else {
+                                    let r = self.marker.get_binding(var_num);
+                                    // let r = self.marker.mark_cut_var(var_num, chunk_num);
+                                    code.push_back(instr!("cut", r));
+                                }
+
+                                if self.marker.in_tail_position {
+                                    if self.marker.var_data.allocates {
+                                        code.push_back(instr!("deallocate"));
+                                    }
+
+                                    code.push_back(instr!("proceed"));
+                                }
+                            }
+                            &QueryTerm::LocalCut(var_num) => {
+                                let code = branch_code_stack.code(code);
+                                let r = self.marker.get_binding(var_num);
+                                // let r = self.marker.mark_cut_var(var_num, chunk_num);
+                                code.push_back(instr!("cut", r));
+
+                                if self.marker.in_tail_position {
+                                    if self.marker.var_data.allocates {
+                                        code.push_back(instr!("deallocate"));
+                                    }
+
+                                    code.push_back(instr!("proceed"));
+                                }
+                            }
+                            &QueryTerm::Clause(
+                                _,
+                                ClauseType::BuiltIn(BuiltInClauseType::Is(..)),
+                                ref terms,
+                                call_policy,
+                            ) => self.compile_is_call(terms, branch_code_stack.code(code), term_loc, call_policy)?,
+                            &QueryTerm::Clause(_, ClauseType::Inlined(ref ct), ref terms, _) => {
+                                self.compile_inlined(ct, terms, term_loc, branch_code_stack.code(code))?
+                            }
+                            &QueryTerm::Fail => {
+                                branch_code_stack.code(code).push_back(instr!("$fail"));
+                            }
+                            term @ &QueryTerm::Clause(..) => {
+                                self.compile_query_line(term, term_loc, branch_code_stack.code(code));
 
-                        if self.marker.max_reg_allocated() > MAX_ARITY {
-                            return Err(CompilationError::ExceededMaxArity);
+                                if self.marker.max_reg_allocated() > MAX_ARITY {
+                                    return Err(CompilationError::ExceededMaxArity);
+                                }
+                            }
                         }
                     }
-                }
-            }
-
-            self.marker.reset_contents();
-        }
 
-        Ok(())
-    }
+                    chunk_num += 1;
+                    self.marker.in_tail_position = false;
+                    self.marker.reset_contents();
+                }
+                ClauseItem::FirstBranch(num_branches) => {
+                    branch_code_stack.add_new_branch_stack();
+                    branch_code_stack.add_new_branch();
 
-    fn compile_seq_prelude(&mut self, var_data: &VarData, body: &mut Code) {
-        /*
-        if conjunct_info.allocates() {
-            let perm_vars = conjunct_info.perm_vars();
+                    self.marker.add_branch_stack(num_branches);
+                    self.marker.add_branch();
+                }
+                ClauseItem::NextBranch => {
+                    branch_code_stack.add_new_branch();
+                    self.marker.add_branch();
+                    self.marker.incr_current_branch();
+                }
+                ClauseItem::BranchEnd(depth) => {
+                    if !clause_iter.in_tail_position() {
+                        let subsumed_hits = branch_code_stack.push_missing_vars(depth, &mut self.marker);
+                        self.marker.pop_branch(depth, subsumed_hits);
+                        branch_code_stack.push_jump_instrs(depth);
+                    } else {
+                        self.marker.drain_branches(depth);
+                    }
 
-            body.push(Instruction::Allocate(perm_vars));
+                    let settings = CodeGenSettings {
+                        non_counted_bt: self.settings.non_counted_bt,
+                        is_extensible: false,
+                        global_clock_tick: None,
+                    };
 
-            if conjunct_info.has_deep_cut {
-                body.push(Instruction::GetLevel(perm_v!(1)));
+                    let branch_code = branch_code_stack.pop_branch(depth, settings);
+                    branch_code_stack.code(code).extend(branch_code);
+                }
             }
         }
-        */
-    }
 
-    fn compile_cleanup(
-        &mut self,
-        code: &mut Code,
-        conjunct_info: &ConjunctInfo,
-        toc: &QueryTerm,
-    ) {
-        // add a proceed to bookend any trailing cuts.
-        match toc {
-            &QueryTerm::BlockedCut | &QueryTerm::UnblockedCut(..) => {
-                code.push(instr!("proceed"));
-            }
-            _ => {}
+        if self.marker.var_data.allocates {
+            code.push_front(instr!("allocate", self.marker.num_perm_vars()));
         }
 
-        // perform lco.
-        let dealloc_index = Self::lco(code);
-
-        if conjunct_info.allocates() {
-            let offset = self.global_jmp_by_locs_offset;
-
-            if let Some(jmp_by_offset) = self.jmp_by_locs[offset..].last_mut() {
-                if *jmp_by_offset == dealloc_index {
-                    *jmp_by_offset += 1;
-                }
-            }
-
-            code.insert(dealloc_index, instr!("deallocate"));
-        }
+        Ok(())
     }
 
-    pub(crate) fn compile_rule(&mut self, rule: &Rule) -> Result<Code, CompilationError> {
-        // let iter = ChunkedIterator::from_rule(rule);
-        // let conjunct_info = self.collect_var_data(iter);
-
-        let &Rule {
-            head: (_, ref args, ref p1),
-            ref clauses,
-            ref var_data,
-        } = rule;
-
-        let mut code = Code::new();
+    pub(crate) fn compile_rule(&mut self, rule: &Rule, var_data: VarData) -> Result<Code, CompilationError> {
+        let Rule { head: (_, args), clauses } = rule;
+        self.marker.var_data = var_data;
+        let mut code = VecDeque::new();
 
         self.marker.reset_at_head(args);
-        self.compile_seq_prelude(&var_data, &mut code);
 
-        let iter = FactIterator::from_rule_head_clause(args);
-        let mut fact = self.compile_target::<FactInstruction, _>(iter, GenContext::Head);
+        let iter = FactIterator::from_rule_head_clause(&args);
+        let fact = self.compile_target::<FactInstruction, _>(iter, GenContext::Head);
 
         if self.marker.max_reg_allocated() > MAX_ARITY {
             return Err(CompilationError::ExceededMaxArity);
         }
 
         self.marker.reset_free_list();
+        code.extend(fact.into_iter());
 
-        let mut unsafe_var_marker = UnsafeVarMarker::new();
+        self.compile_seq(clauses, &mut code)?;
 
-        if !fact.is_empty() {
-            unsafe_var_marker = self.mark_unsafe_fact_vars(&mut fact);
-            code.extend(fact.into_iter());
-        }
-
-        let iter = ChunkedIterator::from_rule_body(p1, clauses);
-        self.compile_seq(iter, &conjunct_info, &mut code)?;
-
-        unsafe_var_marker.mark_unsafe_instrs(&mut code);
-
-        self.compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1));
-
-        Ok(code)
-    }
-
-    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 Instruction::UnifyValue(r) => {
-                    if !safe_vars.contains(&r) {
-                        *fact_instr = Instruction::UnifyLocalValue(r);
-                        safe_vars.insert(r);
-                    }
-                }
-                &mut Instruction::UnifyVariable(r) => {
-                    safe_vars.insert(r);
-                }
-                _ => {}
-            }
-        }
-
-        UnsafeVarMarker::from_fact_vars(safe_vars)
+        Ok(Vec::from(code))
     }
 
-    pub(crate) fn compile_fact(&mut self, fact: &Fact) -> Result<Code, CompilationError> {
-        self.update_var_count(post_order_iter(term));
-
-        // let mut vs = VariableFixtures::new();
-
-        // vs.mark_vars_in_chunk(post_order_iter(term), term.arity(), GenContext::Head);
-
-        // vs.populate_restricting_sets();
-        // self.marker.drain_var_data(vs, 1);
-
+    pub(crate) fn compile_fact(&mut self, fact: &Fact, var_data: VarData) -> Result<Code, CompilationError> {
         let mut code = Vec::new();
+        self.marker.var_data = var_data;
 
-        if let &Term::Clause(_, _, ref args) = term {
+        if let Term::Clause(_, _, args) = &fact.head {
             self.marker.reset_at_head(args);
 
-            let iter = FactInstruction::iter(term);
-            let mut compiled_fact = self.compile_target::<FactInstruction, _>(
+            let iter = FactInstruction::iter(&fact.head);
+            let compiled_fact = self.compile_target::<FactInstruction, _>(
                 iter,
                 GenContext::Head,
             );
@@ -1023,40 +1021,27 @@ impl<'b> CodeGenerator<'b> {
                 return Err(CompilationError::ExceededMaxArity);
             }
 
-            self.mark_unsafe_fact_vars(&mut compiled_fact);
-
-            if !compiled_fact.is_empty() {
-                code.extend(compiled_fact.into_iter());
-            }
+            code.extend(compiled_fact.into_iter());
         }
 
         code.push(instr!("proceed"));
         Ok(code)
     }
 
-    fn compile_query_line(
-        &mut self,
-        term: &QueryTerm,
-        term_loc: GenContext,
-        code: &mut Code,
-        num_perm_vars_left: usize,
-    ) {
+    fn compile_query_line(&mut self, term: &QueryTerm, term_loc: GenContext, code: &mut CodeDeque) {
         self.marker.reset_arg(term.arity());
 
-        let iter = query_term_post_order_iter(term);
+        let iter = QueryIterator::new(term);
         let query = self.compile_target::<QueryInstruction, _>(iter, term_loc);
 
         code.extend(query.into_iter());
-        self.add_conditional_call(code, term, num_perm_vars_left);
-    }
-
-    #[inline]
-    fn increment_jmp_by_locs_by(&mut self, incr: usize) {
-        let offset = self.global_jmp_by_locs_offset;
 
-        for loc in &mut self.jmp_by_locs[offset..] {
-            *loc += incr;
-        }
+        match term {
+            &QueryTerm::Clause(_, ref ct, _, call_policy) => {
+                self.add_call(code, ct.to_instr(), call_policy);
+            }
+            _ => unreachable!()
+        };
     }
 
     fn split_predicate(clauses: &[PredicateClause]) -> Vec<ClauseSpan> {
@@ -1121,30 +1106,35 @@ impl<'b> CodeGenerator<'b> {
 
     fn compile_pred_subseq<I: Indexer>(
         &mut self,
-        clauses: &[PredicateClause],
+        clauses: &mut [PredicateClause],
         optimal_index: usize,
     ) -> Result<Code, CompilationError> {
         let mut code = VecDeque::new();
         let mut code_offsets = CodeOffsets::new(I::new(), optimal_index + 1);
 
         let mut skip_stub_try_me_else = false;
-        let jmp_by_locs_len = self.jmp_by_locs.len();
+        let clauses_len = clauses.len();
 
-        for (i, clause) in clauses.iter().enumerate() {
+        for (i, clause) in clauses.iter_mut().enumerate() {
             self.marker.reset();
 
             let mut clause_index_info = ClauseIndexInfo::new(code.len());
-            self.global_jmp_by_locs_offset = self.jmp_by_locs.len();
 
             let clause_code = match clause {
-                &PredicateClause::Fact(ref fact, ..) => self.compile_fact(fact)?,
-                &PredicateClause::Rule(ref rule, ..) => self.compile_rule(rule)?,
+                PredicateClause::Fact(fact, var_data) => {
+                    let var_data = std::mem::replace(var_data, VarData::default());
+                    self.compile_fact(&fact, var_data)?
+                }
+                PredicateClause::Rule(rule, var_data) => {
+                    let var_data = std::mem::replace(var_data, VarData::default());
+                    self.compile_rule(&rule, var_data)?
+                }
             };
 
-            if clauses.len() > 1 {
+            if clauses_len > 1 {
                 let choice = match i {
                     0 => self.settings.internal_try_me_else(clause_code.len() + 1),
-                    _ if i == clauses.len() - 1 => self.settings.internal_trust_me(),
+                    _ if i + 1 == clauses_len => self.settings.internal_trust_me(),
                     _ => self.settings.internal_retry_me_else(clause_code.len() + 1),
                 };
 
@@ -1170,45 +1160,23 @@ impl<'b> CodeGenerator<'b> {
             if let Some(arg) = arg {
                 let index = code.len();
 
-                if clauses.len() > 1 || self.settings.is_extensible {
+                if clauses_len > 1 || self.settings.is_extensible {
                     code_offsets.index_term(arg, index, &mut clause_index_info, self.atom_tbl);
                 }
             }
 
-            if !(code_offsets.no_indices() && clauses.len() == 1 && self.settings.is_extensible) {
-                // the peculiar condition of this block, when false,
-                // anticipates code.pop_front() being called about a
-                // dozen lines below.
-
-                if !skip_stub_try_me_else {
-                    // if the condition is false, code_offsets.no_indices() is false,
-                    // so don't repeat the work of the condition on skip_stub_try_me_else
-                    // below.
-                    self.increment_jmp_by_locs_by(code.len());
-                }
-            }
-
             self.skeleton.clauses.push_back(clause_index_info);
             code.extend(clause_code.into_iter());
         }
 
-        let index_code = if clauses.len() > 1 || self.settings.is_extensible {
+        let index_code = if clauses_len > 1 || self.settings.is_extensible {
             code_offsets.compute_indices(skip_stub_try_me_else)
         } else {
             vec![]
         };
 
-        self.global_jmp_by_locs_offset = jmp_by_locs_len;
-
         if !index_code.is_empty() {
             code.push_front(Instruction::IndexingCode(index_code));
-
-            if skip_stub_try_me_else {
-                // skip the TryMeElse(0) also.
-                self.increment_jmp_by_locs_by(2);
-            } else {
-                self.increment_jmp_by_locs_by(1);
-            }
         } else if clauses.len() == 1 && self.settings.is_extensible {
             // the condition is the value of skip_stub_try_me_else, which is
             // true if the predicate is not dynamic. This operation must apply
@@ -1223,7 +1191,7 @@ impl<'b> CodeGenerator<'b> {
 
     pub(crate) fn compile_predicate(
         &mut self,
-        clauses: &Vec<PredicateClause>,
+        mut clauses: Vec<PredicateClause>,
     ) -> Result<Code, CompilationError> {
         let mut code = Code::new();
 
@@ -1234,12 +1202,12 @@ impl<'b> CodeGenerator<'b> {
             let skel_lower_bound = self.skeleton.clauses.len();
             let code_segment = if self.settings.is_dynamic() {
                 self.compile_pred_subseq::<DynamicCodeIndices>(
-                    &clauses[left..right],
+                    &mut clauses[left..right],
                     instantiated_arg_index,
                 )?
             } else {
                 self.compile_pred_subseq::<StaticCodeIndices>(
-                    &clauses[left..right],
+                    &mut clauses[left..right],
                     instantiated_arg_index,
                 )?
             };
@@ -1271,12 +1239,17 @@ impl<'b> CodeGenerator<'b> {
                 }
             }
 
-            self.increment_jmp_by_locs_by(code.len());
-            self.global_jmp_by_locs_offset = self.jmp_by_locs.len();
-
             code.extend(code_segment.into_iter());
         }
 
+        /*
+        for line in &code {
+            println!("{:?}", line);
+        }
+
+        println!("");
+        */
+
         Ok(code)
     }
 }
index 2ad19cab54a6d098e3c9c42289f036abfc98b163..2f8d442ef464bb1e4ed2ad909689d556085acfed 100644 (file)
-use indexmap::IndexMap;
-
 use crate::allocator::*;
-use crate::fixtures::*;
+use crate::codegen::SubsumedBranchHits;
 use crate::forms::Level;
 use crate::instructions::*;
-use crate::machine::machine_indices::*;
+use crate::machine::disjuncts::VarData;
 use crate::parser::ast::*;
 use crate::targets::*;
+use crate::variable_records::*;
 
-use crate::temp_v;
-
+use bit_set::*;
+use bitvec::prelude::*;
 use fxhash::FxBuildHasher;
+use indexmap::IndexMap;
 
 use std::cell::Cell;
-use std::collections::BTreeSet;
+use std::collections::VecDeque;
+
+pub type BranchHits = IndexMap<usize, BitVec, FxBuildHasher>; // key: var_num, value: branch arm occurrences.
+
+#[derive(Debug, Default)]
+pub struct BranchOccurrences {
+    pub hits: BranchHits,
+    pub shallow_safety: BitSet<usize>, // unset means safe, set means unsafe (after the branch merge)
+    pub deep_safety: BitSet<usize>,
+    pub num_branches: usize,
+    pub current_branch: usize,
+    pub subsumed_hits: SubsumedBranchHits,
+}
+
+impl BranchOccurrences {
+    fn new(num_branches: usize) -> Self {
+        Self {
+            hits: BranchHits::with_hasher(FxBuildHasher::default()),
+            shallow_safety: BitSet::default(),
+            deep_safety: BitSet::default(),
+            num_branches,
+            current_branch: 0,
+            subsumed_hits: SubsumedBranchHits::with_hasher(FxBuildHasher::default()),
+        }
+    }
+}
 
 #[derive(Debug)]
 pub(crate) struct DebrayAllocator {
-    bindings: IndexMap<Var, VarAlloc, FxBuildHasher>,
+    pub(crate) var_data: VarData, // var_data replaces bindings.
+    pub(crate) branch_stack: Vec<BranchOccurrences>,
+    pub(crate) in_tail_position: bool,
+    // bindings: IndexMap<usize, VarWitness, FxBuildHasher>, // VarNum -> VarWitness
     arg_c: usize,
     temp_lb: usize,
+    perm_lb: usize,
     arity: usize, // 0 if not at head.
-    contents: IndexMap<usize, Var, FxBuildHasher>,
-    in_use: BTreeSet<usize>,
-    free_list: Vec<usize>,
+    shallow_temp_mappings: IndexMap<usize, usize, FxBuildHasher>,
+    in_use: BitSet<usize>, // deep and non-var allocations
+    temp_free_list: Vec<usize>,
+    perm_free_list: VecDeque<(usize, usize)>, // chunk_num, var_num
 }
 
 impl DebrayAllocator {
-    fn is_curr_arg_distinct_from(&self, var: &Var) -> bool {
-        match self.contents.get(&self.arg_c) {
-            Some(t_var) if *t_var != *var => true,
+    pub(crate) fn add_branch_occurrence(&mut self, var_num: usize) {
+        if let Some(occurrences) = self.branch_stack.last_mut() {
+            debug_assert!(occurrences.current_branch < occurrences.num_branches);
+
+            let num_branches = occurrences.num_branches;
+
+            let entry = occurrences.hits.entry(var_num)
+                .or_insert_with(|| BitVec::repeat(false, num_branches));
+
+            entry.set(occurrences.current_branch, true);
+            occurrences.subsumed_hits.insert(var_num);
+        }
+    }
+
+    pub(crate) fn add_branch_stack(&mut self, num_branches: usize) {
+        self.branch_stack.push(BranchOccurrences::new(num_branches));
+    }
+
+    pub(crate) fn add_branch(&mut self) {
+        let branch_occurrences = self.branch_stack.last_mut().unwrap();
+
+        for var_num in branch_occurrences.subsumed_hits.drain(..) {
+            match &mut self.var_data.records[var_num].allocation {
+                VarAlloc::Perm(_, ref mut allocation) => {
+                    match allocation {
+                        PermVarAllocation::Done { shallow_safety, deep_safety, .. } => {
+                            if !shallow_safety.unneeded() {
+                                branch_occurrences.shallow_safety.insert(var_num);
+                            }
+
+                            if !deep_safety.unneeded() {
+                                branch_occurrences.deep_safety.insert(var_num);
+                            }
+                        }
+                        _ => {
+                            unreachable!();
+                        }
+                    }
+
+                    *allocation = PermVarAllocation::Pending;
+                }
+                _ => unreachable!(),
+            }
+        }
+    }
+
+    #[inline]
+    pub(crate) fn incr_current_branch(&mut self) {
+        let branch_occurrences = self.branch_stack.last_mut().unwrap();
+        branch_occurrences.current_branch += 1;
+    }
+
+    #[inline]
+    pub(crate) fn drain_branches(&mut self, depth: usize) -> std::vec::Drain<BranchOccurrences> {
+        let start_idx = self.branch_stack.len() - depth;
+        self.branch_stack.drain(start_idx ..)
+    }
+
+    pub(crate) fn pop_branch(&mut self, depth: usize, subsumed_hits: SubsumedBranchHits) {
+        let removed_branches = self.drain_branches(depth);
+
+        let (deep_safety, shallow_safety) = removed_branches
+            .into_iter()
+            .fold((BitSet::default(), BitSet::default()),
+                  |(mut deep_safety, mut shallow_safety), branch_occurrences| {
+                      deep_safety.union_with(&branch_occurrences.deep_safety);
+                      shallow_safety.union_with(&branch_occurrences.shallow_safety);
+
+                      (deep_safety, shallow_safety)
+                  });
+
+        let (deep_safety, shallow_safety) = match self.branch_stack.last_mut() {
+            Some(latest_branch) => {
+                latest_branch.deep_safety.union_with(&deep_safety);
+                latest_branch.shallow_safety.union_with(&shallow_safety);
+
+                (&latest_branch.deep_safety, &latest_branch.shallow_safety)
+            }
+            None => (&deep_safety, &shallow_safety)
+        };
+
+        for var_num in subsumed_hits.iter().cloned() {
+            match &mut self.var_data.records[var_num].allocation {
+                VarAlloc::Perm(_, ref mut allocation) => {
+                    let shallow_safety = VarSafetyStatus::needed_if(
+                        shallow_safety.contains(var_num),
+                    );
+
+                    let deep_safety = VarSafetyStatus::needed_if(
+                        deep_safety.contains(var_num),
+                    );
+
+                    *allocation = PermVarAllocation::Done { shallow_safety, deep_safety };
+                }
+                _ => unreachable!()
+            }
+        }
+
+        if self.branch_stack.len() > 0 {
+            for var_num in subsumed_hits {
+                self.add_branch_occurrence(var_num);
+            }
+        }
+    }
+
+    fn is_curr_arg_distinct_from(&self, var_num: usize) -> bool {
+        match self.shallow_temp_mappings.get(&self.arg_c).cloned() {
+            Some(t_var) => t_var != var_num,
             _ => false,
         }
     }
 
-    fn occurs_shallowly_in_head(&self, var: &Var, r: usize) -> bool {
-        match self.bindings.get(var).unwrap() {
-            &VarAlloc::Temp(_, _, ref tvd) => tvd.use_set.contains(&(GenContext::Head, r)),
+    fn occurs_shallowly_in_head(&self, var_num: usize, r: usize) -> bool {
+        match &self.var_data.records[var_num].allocation {
+            VarAlloc::Temp { temp_var_data, term_loc: GenContext::Head, .. } => {
+                temp_var_data.use_set.contains(&(GenContext::Head, r))
+            }
             _ => false,
         }
     }
@@ -44,13 +181,13 @@ impl DebrayAllocator {
     #[inline]
     fn is_in_use(&self, r: usize) -> bool {
         let in_use_range = r <= self.arity && r >= self.arg_c;
-        in_use_range || self.in_use.contains(&r)
+        in_use_range || self.in_use.contains(r)
     }
 
-    fn alloc_with_cr(&self, var: &Var) -> usize {
-        match self.bindings.get(var) {
-            Some(&VarAlloc::Temp(_, _, ref tvd)) => {
-                for &(_, reg) in tvd.use_set.iter() {
+    fn alloc_with_cr(&self, var_num: usize) -> usize {
+        match &self.var_data.records[var_num].allocation {
+            VarAlloc::Temp { temp_var_data, .. } => {
+                for &(_, reg) in temp_var_data.use_set.iter() {
                     if !self.is_in_use(reg) {
                         return reg;
                     }
@@ -60,7 +197,7 @@ impl DebrayAllocator {
 
                 for reg in self.temp_lb.. {
                     if !self.is_in_use(reg) {
-                        if !tvd.no_use_set.contains(&reg) {
+                        if !temp_var_data.no_use_set.contains(reg) {
                             result = reg;
                             break;
                         }
@@ -73,10 +210,10 @@ impl DebrayAllocator {
         }
     }
 
-    fn alloc_with_ca(&self, var: &Var) -> usize {
-        match self.bindings.get(var) {
-            Some(&VarAlloc::Temp(_, _, ref tvd)) => {
-                for &(_, reg) in tvd.use_set.iter() {
+    fn alloc_with_ca(&self, var_num: usize) -> usize {
+        match &self.var_data.records[var_num].allocation {
+            VarAlloc::Temp { temp_var_data, .. } => {
+                for &(_, reg) in temp_var_data.use_set.iter() {
                     if !self.is_in_use(reg) {
                         return reg;
                     }
@@ -86,8 +223,8 @@ impl DebrayAllocator {
 
                 for reg in self.temp_lb.. {
                     if !self.is_in_use(reg) {
-                        if !tvd.no_use_set.contains(&reg) {
-                            if !tvd.conflict_set.contains(&reg) {
+                        if !temp_var_data.no_use_set.contains(reg) {
+                            if !temp_var_data.conflict_set.contains(reg) {
                                 result = reg;
                                 break;
                             }
@@ -101,22 +238,25 @@ impl DebrayAllocator {
         }
     }
 
-    fn alloc_in_last_goal_hint(&self, chunk_num: usize) -> Option<(Var, usize)> {
+    fn alloc_in_last_goal_hint(&self, chunk_num: usize) -> Option<(usize, usize)> {
         // we want to allocate a register to the k^{th} parameter, par_k.
         // par_k may not be a temporary variable.
         let k = self.arg_c;
 
-        match self.contents.get(&k) {
+        match self.shallow_temp_mappings.get(&k).cloned() {
             Some(t_var) => {
                 // suppose this branch fires. then t_var is a
                 // temp. var. belonging to the current chunk.
                 // consider its use set. T == par_k iff
                 // (GenContext::Last(_), k) is in t_var.use_set.
 
-                let tvd = self.bindings.get(t_var).unwrap();
-                if let &VarAlloc::Temp(_, _, ref tvd) = tvd {
-                    if !tvd.use_set.contains(&(GenContext::Last(chunk_num), k)) {
-                        return Some((t_var.clone(), self.alloc_with_ca(t_var)));
+                match &self.var_data.records[t_var].allocation {
+                    VarAlloc::Temp { temp_var_data, .. } => {
+                        if !temp_var_data.use_set.contains(&(GenContext::Last(chunk_num), k)) {
+                            return Some((t_var, self.alloc_with_ca(t_var)));
+                        }
+                    }
+                    _ => {
                     }
                 }
 
@@ -129,21 +269,21 @@ impl DebrayAllocator {
     fn evacuate_arg<'a, Target: CompilationTarget<'a>>(
         &mut self,
         chunk_num: usize,
-        code: &mut Code,
+        code: &mut CodeDeque,
     ) {
         match self.alloc_in_last_goal_hint(chunk_num) {
-            Some((var, r)) => {
+            Some((var_num, r)) => {
                 let k = self.arg_c;
 
                 if r != k {
                     let r = RegType::Temp(r);
 
-                    code.push(Target::move_to_register(r, k));
+                    code.push_back(Target::move_to_register(r, k));
 
-                    self.contents.swap_remove(&k);
-                    self.contents.insert(r.reg_num(), var.clone());
+                    self.shallow_temp_mappings.swap_remove(&k);
+                    self.shallow_temp_mappings.insert(r.reg_num(), var_num);
 
-                    self.record_register(var, r);
+                    self.var_data.records[var_num].allocation.set_register(r.reg_num());
                     self.in_use.insert(r.reg_num());
                 }
             }
@@ -153,27 +293,27 @@ impl DebrayAllocator {
 
     fn alloc_reg_to_var<'a, Target: CompilationTarget<'a>>(
         &mut self,
-        var: &Var,
+        var_num: usize,
         lvl: Level,
         term_loc: GenContext,
-        target: &mut Vec<Instruction>,
+        target: &mut CodeDeque,
     ) -> usize {
         match term_loc {
             GenContext::Head => {
                 if let Level::Shallow = lvl {
                     self.evacuate_arg::<Target>(0, target);
-                    self.alloc_with_cr(var)
+                    self.alloc_with_cr(var_num)
                 } else {
-                    self.alloc_with_ca(var)
+                    self.alloc_with_ca(var_num)
                 }
             }
-            GenContext::Mid(_) => self.alloc_with_ca(var),
+            GenContext::Mid(_) => self.alloc_with_ca(var_num),
             GenContext::Last(chunk_num) => {
                 if let Level::Shallow = lvl {
                     self.evacuate_arg::<Target>(chunk_num, target);
-                    self.alloc_with_cr(var)
+                    self.alloc_with_cr(var_num)
                 } else {
-                    self.alloc_with_ca(var)
+                    self.alloc_with_ca(var_num)
                 }
             }
         }
@@ -182,15 +322,15 @@ impl DebrayAllocator {
     fn alloc_reg_to_non_var(&mut self) -> usize {
         let mut final_index = 0;
 
-        while let Some(r) = self.free_list.pop() {
-            if !self.in_use.contains(&r) {
+        while let Some(r) = self.temp_free_list.pop() {
+            if !self.is_in_use(r) {
                 self.in_use.insert(r);
                 return r;
             }
         }
 
         for index in self.temp_lb.. {
-            if !self.in_use.contains(&index) {
+            if !self.in_use.contains(index) {
                 final_index = index;
                 self.in_use.insert(final_index);
                 break;
@@ -201,38 +341,194 @@ impl DebrayAllocator {
         final_index
     }
 
-    fn in_place(&self, var: &Var, term_loc: GenContext, r: RegType, k: usize) -> bool {
+    fn in_place(&self, var_num: usize, term_loc: GenContext, r: RegType, k: usize) -> bool {
         match term_loc {
             GenContext::Head if !r.is_perm() => r.reg_num() == k,
-            _ => match self.bindings().get(var).unwrap() {
-                &VarAlloc::Temp(_, o, _) if r.reg_num() == k => o == k,
-                _ => false,
+            _ => {
+                match &self.var_data.records[var_num].allocation {
+                    &VarAlloc::Temp { temp_reg, .. } if r.reg_num() == k =>
+                        temp_reg == k,
+                    _ => false,
+                }
             },
         }
     }
 
+    fn alloc_perm_var(&mut self, var_num: usize, chunk_num: usize) -> usize {
+        let p = if let Some(p) = self.pop_free_perm(chunk_num) {
+            p
+        } else {
+            let p = self.perm_lb;
+            self.perm_lb += 1;
+
+            p
+        };
+
+        self.var_data.records[var_num].allocation = VarAlloc::Perm(p, PermVarAllocation::done());
+        p
+    }
+
     pub fn add_to_free_list(&mut self, r: RegType) {
         if let RegType::Temp(r) = r {
-            self.in_use.remove(&r);
-            self.free_list.push(r);
+            self.in_use.remove(r);
+            self.temp_free_list.push(r);
         }
     }
 
     pub fn reset_free_list(&mut self) {
-        self.free_list.clear();
+        self.temp_free_list.clear();
+    }
+
+    #[inline(always)]
+    pub fn get_binding(&self, var_num: usize) -> RegType {
+        self.var_data.records[var_num].allocation.as_reg_type()
+    }
+
+    pub fn num_perm_vars(&self) -> usize {
+        self.perm_lb - 1
+    }
+
+    pub fn increment_running_count(&mut self, var_num: usize) {
+        self.var_data.records[var_num].running_count += 1;
+    }
+
+    fn pop_free_perm(&mut self, chunk_num: usize) -> Option<usize> {
+        if let Some((perm_chunk_num, var_num)) = self.perm_free_list.front().cloned() {
+            if chunk_num == perm_chunk_num {
+                None
+            } else {
+                self.perm_free_list.pop_front();
+
+                match &mut self.var_data.records[var_num].allocation {
+                    &mut VarAlloc::Perm(p, ref mut allocation) => {
+                        *allocation = PermVarAllocation::Pending;
+                        Some(p)
+                    }
+                    _ => unreachable!()
+                }
+            }
+        } else {
+            None
+        }
+    }
+
+    pub(crate) fn mark_temp_to_safe_perm(&mut self, var_num: usize) {
+        match &self.var_data.records[var_num].allocation {
+            &VarAlloc::Temp { to_perm_var_num: Some(perm_var_num), .. } => {
+                match &mut self.var_data.records[perm_var_num].allocation {
+                    VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => {
+                        *deep_safety = VarSafetyStatus::Unneeded;
+                        *shallow_safety = VarSafetyStatus::Unneeded;
+                    }
+                    _ => unreachable!()
+                }
+            }
+            _ => {
+            }
+        }
+    }
+
+    fn mark_safe_var(&mut self, var_num: usize, lvl: Level, term_loc: GenContext) {
+        match &mut self.var_data.records[var_num].allocation {
+            VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => {
+                // GetVariable in head chunk is considered safe.
+                if lvl == Level::Deep {
+                    *deep_safety = VarSafetyStatus::Unneeded;
+                    *shallow_safety = VarSafetyStatus::Unneeded;
+                } else if term_loc == GenContext::Head {
+                    *shallow_safety = VarSafetyStatus::Unneeded;
+                } else {
+                    if let Some(temp_var_num) = self.shallow_temp_mappings.get(&self.arg_c).cloned() {
+                        match &mut self.var_data.records[temp_var_num].allocation {
+                            VarAlloc::Temp { ref mut to_perm_var_num, .. } => {
+                                *to_perm_var_num = Some(var_num);
+                            }
+                            _ => unreachable!()
+                        }
+                    }
+                }
+            }
+            VarAlloc::Temp { ref mut safety, .. } => {
+                *safety = VarSafetyStatus::Unneeded;
+            }
+            _ => {
+                unreachable!()
+            }
+        }
+    }
+
+    fn argument_to_value<'a, Target: CompilationTarget<'a>>(
+        &mut self,
+        var_num: usize,
+        r: RegType,
+        arg_c: usize,
+    ) -> Instruction {
+        match &mut self.var_data.records[var_num].allocation {
+            VarAlloc::Perm(_, PermVarAllocation::Done { ref mut shallow_safety, .. }) => {
+                if !self.in_tail_position || shallow_safety.unneeded() {
+                    Target::argument_to_value(r, arg_c)
+                } else {
+                    *shallow_safety = VarSafetyStatus::Unneeded;
+                    Target::unsafe_argument_to_value(r, arg_c)
+                }
+            }
+            VarAlloc::Temp { ref mut safety, .. } => {
+                if safety.unneeded() {
+                    Target::argument_to_value(r, arg_c)
+                } else {
+                    *safety = VarSafetyStatus::Unneeded;
+                    Target::unsafe_argument_to_value(r, arg_c)
+                }
+            }
+            _ => {
+                unreachable!()
+            }
+        }
+    }
+
+    fn subterm_to_value<'a, Target: CompilationTarget<'a>>(
+        &mut self,
+        var_num: usize,
+        r: RegType,
+    ) -> Instruction {
+        match &mut self.var_data.records[var_num].allocation {
+            VarAlloc::Perm(_, PermVarAllocation::Done { ref mut deep_safety, .. }) => {
+                if deep_safety.unneeded() {
+                    Target::subterm_to_value(r)
+                } else {
+                    *deep_safety = VarSafetyStatus::Unneeded;
+                    Target::unsafe_subterm_to_value(r)
+                }
+            }
+            VarAlloc::Temp { ref mut safety, .. } => {
+                if safety.unneeded() {
+                    Target::subterm_to_value(r)
+                } else {
+                    *safety = VarSafetyStatus::Unneeded;
+                    Target::unsafe_subterm_to_value(r)
+                }
+            }
+            _ => {
+                unreachable!()
+            }
+        }
     }
 }
 
 impl Allocator for DebrayAllocator {
     fn new() -> DebrayAllocator {
-        DebrayAllocator {
+        Self {
+            var_data: VarData::default(),
+            in_tail_position: false,
             arity: 0,
             arg_c: 1,
             temp_lb: 1,
-            bindings: IndexMap::with_hasher(FxBuildHasher::default()),
-            contents: IndexMap::with_hasher(FxBuildHasher::default()),
-            in_use: BTreeSet::new(),
-            free_list: vec![],
+            perm_lb: 1,
+            shallow_temp_mappings: IndexMap::with_hasher(FxBuildHasher::default()),
+            in_use: BitSet::default(),
+            temp_free_list: vec![],
+            perm_free_list: VecDeque::new(),
+            branch_stack: vec![],
         }
     }
 
@@ -240,12 +536,12 @@ impl Allocator for DebrayAllocator {
         &mut self,
         lvl: Level,
         term_loc: GenContext,
-        code: &mut Code,
+        code: &mut CodeDeque,
     ) {
         let r = RegType::Temp(self.alloc_reg_to_non_var());
 
         match lvl {
-            Level::Deep => code.push(Target::subterm_to_variable(r)),
+            Level::Deep => code.push_back(Target::subterm_to_variable(r)),
             Level::Root | Level::Shallow => {
                 let k = self.arg_c;
 
@@ -255,7 +551,7 @@ impl Allocator for DebrayAllocator {
 
                 self.arg_c += 1;
 
-                code.push(Target::argument_to_variable(r, k));
+                code.push_back(Target::argument_to_variable(r, k));
             }
         };
     }
@@ -265,7 +561,7 @@ impl Allocator for DebrayAllocator {
         lvl: Level,
         term_loc: GenContext,
         cell: &'a Cell<RegType>,
-        code: &mut Code,
+        code: &mut CodeDeque,
     ) {
         let r = cell.get();
 
@@ -292,39 +588,49 @@ impl Allocator for DebrayAllocator {
 
     fn mark_var<'a, Target: CompilationTarget<'a>>(
         &mut self,
-        var: Var,
+        var_num: usize,
         lvl: Level,
         cell: &'a Cell<VarReg>,
         term_loc: GenContext,
-        code: &mut Code,
+        code: &mut CodeDeque,
     ) {
-        let (r, is_new_var) = match self.get(var.clone()) {
+        let (r, is_new_var) = match self.get_binding(var_num) {
             RegType::Temp(0) => {
-                // here, r is temporary *and* unassigned.
-                let o = self.alloc_reg_to_var::<Target>(&var, lvl, term_loc, code);
+                let o = self.alloc_reg_to_var::<Target>(var_num, lvl, term_loc, code);
                 cell.set(VarReg::Norm(RegType::Temp(o)));
 
                 (RegType::Temp(o), true)
             }
             RegType::Perm(0) => {
-                let pr = cell.get().norm();
-                self.record_register(var.clone(), pr);
+                let p = self.alloc_perm_var(var_num, term_loc.chunk_num());
+                (RegType::Perm(p), true)
+            }
+            r @ RegType::Perm(_) => {
+                let is_new_var = match &mut self.var_data.records[var_num].allocation {
+                    VarAlloc::Perm(_, allocation) => if allocation.pending() {
+                        *allocation = PermVarAllocation::done();
+                        true
+                    } else {
+                        false
+                    },
+                    _ => unreachable!(),
+                };
 
-                (pr, true)
+                (r, is_new_var)
             }
             r => (r, false),
         };
 
-        self.mark_reserved_var::<Target>(var, lvl, cell, term_loc, code, r, is_new_var);
+        self.mark_reserved_var::<Target>(var_num, lvl, cell, term_loc, code, r, is_new_var);
     }
 
     fn mark_reserved_var<'a, Target: CompilationTarget<'a>>(
         &mut self,
-        var: Var,
+        var_num: usize,
         lvl: Level,
         cell: &'a Cell<VarReg>,
         term_loc: GenContext,
-        code: &mut Code,
+        code: &mut CodeDeque,
         r: RegType,
         is_new_var: bool,
     ) {
@@ -332,86 +638,104 @@ impl Allocator for DebrayAllocator {
             Level::Root | Level::Shallow => {
                 let k = self.arg_c;
 
-                if self.is_curr_arg_distinct_from(&var) {
+                if self.is_curr_arg_distinct_from(var_num) {
                     self.evacuate_arg::<Target>(term_loc.chunk_num(), code);
                 }
 
-                self.arg_c += 1;
-
                 cell.set(VarReg::ArgAndNorm(r, k));
 
-                if !self.in_place(&var, term_loc, r, k) {
+                if !self.in_place(var_num, term_loc, r, k) {
                     if is_new_var {
-                        code.push(Target::argument_to_variable(r, k));
+                        self.mark_safe_var(var_num, lvl, term_loc);
+                        code.push_back(Target::argument_to_variable(r, k));
                     } else {
-                        code.push(Target::argument_to_value(r, k));
+                        code.push_back(self.argument_to_value::<Target>(var_num, r, k));
                     }
                 }
+
+                self.arg_c += 1;
             }
             Level::Deep if is_new_var => {
                 if let GenContext::Head = term_loc {
-                    if self.occurs_shallowly_in_head(&var, r.reg_num()) {
-                        code.push(Target::subterm_to_value(r));
+                    if self.occurs_shallowly_in_head(var_num, r.reg_num()) {
+                        code.push_back(self.subterm_to_value::<Target>(var_num, r));
                     } else {
-                        code.push(Target::subterm_to_variable(r));
+                        self.mark_safe_var(var_num, lvl, term_loc);
+                        code.push_back(Target::subterm_to_variable(r));
                     }
                 } else {
-                    code.push(Target::subterm_to_variable(r));
+                    self.mark_safe_var(var_num, lvl, term_loc);
+                    code.push_back(Target::subterm_to_variable(r));
                 }
             }
-            Level::Deep => code.push(Target::subterm_to_value(r)),
-        };
+            Level::Deep => code.push_back(self.subterm_to_value::<Target>(var_num, r)),
+        }
+
+        let o = r.reg_num();
 
         if !r.is_perm() {
-            let o = r.reg_num();
+            self.shallow_temp_mappings.insert(o, var_num);
+        } else if r.is_perm() && is_new_var {
+            self.add_branch_occurrence(var_num);
+        }
+
+        let record = &mut self.var_data.records[var_num];
+
+        record.allocation.set_register(o);
+
+        if record.running_count < record.num_occurrences {
+            record.running_count += 1;
+        } else if r.is_perm() {
+            match &mut self.var_data.records[var_num].allocation {
+                VarAlloc::Perm(_, allocation) => *allocation = PermVarAllocation::Pending,
+                _ => unreachable!(),
+            }
+
+            self.perm_free_list.push_back((term_loc.chunk_num(), var_num));
+        }
 
-            self.contents.insert(o, var.clone());
-            self.record_register(var.clone(), r);
-            self.in_use.insert(o);
+        self.in_use.insert(o);
+    }
+
+    fn mark_cut_var(&mut self, var_num: usize, chunk_num: usize) -> RegType {
+        match self.get_binding(var_num) {
+            RegType::Perm(0) | RegType::Temp(0) => {
+                RegType::Perm(self.alloc_perm_var(var_num, chunk_num))
+            }
+            r => r,
         }
     }
 
     fn reset(&mut self) {
-        self.bindings.clear();
-        self.contents.clear();
+        self.perm_lb = 1;
+        self.shallow_temp_mappings.clear();
         self.in_use.clear();
-        self.free_list.clear();
+        self.temp_free_list.clear();
     }
 
     fn reset_contents(&mut self) {
-        self.contents.clear();
         self.in_use.clear();
-        self.free_list.clear();
+        self.shallow_temp_mappings.clear();
+        self.temp_free_list.clear();
     }
 
     fn advance_arg(&mut self) {
         self.arg_c += 1;
     }
 
-    fn bindings(&self) -> &AllocVarDict {
-        &self.bindings
-    }
-
-    fn bindings_mut(&mut self) -> &mut AllocVarDict {
-        &mut self.bindings
-    }
-
-    fn take_bindings(self) -> AllocVarDict {
-        self.bindings
-    }
-
     fn reset_at_head(&mut self, args: &Vec<Term>) {
         self.reset_arg(args.len());
         self.arity = args.len();
 
         for (idx, arg) in args.iter().enumerate() {
             if let &Term::Var(_, ref var) = arg {
-                let r = self.get(var.clone());
+                let var_num = var.to_var_num().unwrap();
+                let r = self.get_binding(var_num);
 
                 if !r.is_perm() && r.reg_num() == 0 {
                     self.in_use.insert(idx + 1);
-                    self.contents.insert(idx + 1, var.clone());
-                    self.record_register(var.clone(), temp_v!(idx + 1));
+                    self.shallow_temp_mappings.insert(idx + 1, var_num);
+                    self.var_data.records[var_num].allocation.set_register(idx + 1);
                 }
             }
         }
diff --git a/src/fixtures.rs b/src/fixtures.rs
deleted file mode 100644 (file)
index 6673432..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-use crate::forms::*;
-use crate::instructions::*;
-use crate::machine::disjuncts::ClassifyInfo;
-use crate::parser::ast::*;
-
-use bit_set::*;
-use indexmap::{IndexMap, IndexSet};
-
-pub(crate) type OccurrenceSet = IndexSet<(GenContext, usize)>;
-
-#[derive(Debug)]
-pub(crate) struct TempVarData {
-    pub(crate) last_term_arity: usize,
-    pub(crate) use_set: OccurrenceSet,
-    pub(crate) no_use_set: BitSet<usize>,
-    pub(crate) conflict_set: BitSet<usize>,
-}
-
-#[derive(Debug)]
-pub(crate) struct TempVarStatus {
-    chunk_num: usize,
-    temp_var_data: TempVarData,
-}
-
-// Perm: 0 initially, a stack register once processed.
-// Temp: labeled with chunk_num and temp offset (unassigned if 0).
-#[derive(Debug)]
-pub(crate) enum VarAlloc {
-    Perm(usize),
-    Temp(usize, usize, TempVarData),
-}
-
-impl VarAlloc {
-    pub(crate) fn as_reg_type(&self) -> RegType {
-        match self {
-            &VarAlloc::Temp(_, r, _) => RegType::Temp(r),
-            &VarAlloc::Perm(r) => RegType::Perm(r),
-        }
-    }
-}
-
-impl TempVarData {
-    pub(crate) fn new(last_term_arity: usize) -> Self {
-        TempVarData {
-            last_term_arity: last_term_arity,
-            use_set: BitSet::<usize>::new(),
-            no_use_set: BitSet::new(),
-            conflict_set: BitSet::new(),
-        }
-    }
-
-    pub(crate) fn uses_reg(&self, reg: usize) -> bool {
-        for &(_, nreg) in self.use_set.iter() {
-            if reg == nreg {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    pub(crate) fn populate_conflict_set(&mut self) {
-        if self.last_term_arity > 0 {
-            let arity = self.last_term_arity;
-            let mut conflict_set: BitSet<usize> = (1..arity).collect();
-
-            for &(_, reg) in self.use_set.iter() {
-                conflict_set.remove(reg);
-            }
-
-            self.conflict_set = conflict_set;
-        }
-    }
-}
-
-#[derive(Debug)]
-pub(crate) struct VariableFixtures {
-    temp_vars: IndexMap<usize, TempVarStatus>,
-}
-
-impl VariableFixtures {
-    pub(crate) fn new() -> Self {
-        VariableFixtures {
-            temp_vars: IndexMap::new(),
-        }
-    }
-
-    // computes no_use and conflict sets for all temp vars.
-    pub(crate) fn populate_restricting_sets(&mut self) {
-        // three stages:
-        // 1. move the use sets of each variable to a local IndexMap, use_set
-        // (iterate mutably, swap mutable refs).
-        // 2. drain use_set. For each use set of U, add into the
-        // no-use sets of appropriate variables T =/= U.
-        // 3. Move the use sets back to their original locations in the fixture.
-        // Compute the conflict set of u.
-
-        // 1.
-        let mut use_sets: IndexMap<usize, OccurrenceSet> = IndexMap::new();
-
-        for (var_gen_index, ref mut var_status) in self.temp_vars.iter_mut() {
-            let TempVarStatus { ref mut temp_var_data, .. } = var_status;
-            let mut use_set = OccurrenceSet::new();
-
-            std::mem::swap(&mut temp_var_data.use_set, &mut use_set);
-            use_sets.insert(var_gen_index, use_set);
-        }
-
-        for (u, use_set) in use_sets.drain(..) {
-            // 2.
-            for &(term_loc, reg) in use_set.iter() {
-                if let GenContext::Last(cn_u) = term_loc {
-                    for (var_gen_index, ref mut var_status) in self.terms_vars.iter_mut() {
-                        let TempVarStatus { chunk_num, ref mut temp_var_data } = var_status;
-
-                        if cn_u == chunk_num && u != var_gen_index {
-                            if !temp_var_data.uses_reg(reg) {
-                                temp_var_data.no_use_set.insert(reg);
-                            }
-                        }
-                    }
-                }
-            }
-
-            // 3.
-            let TempVarStatus { ref mut temp_var_data, ..} = self.temp_vars.get_mut(u).unwrap();
-
-            temp_var_data.use_set = use_set;
-            temp_var_data.populate_conflict_set();
-        }
-    }
-
-    fn record_temp_info(&mut self, tvd: &mut TempVarData, arg_c: usize, term_loc: GenContext) {
-        match term_loc {
-            GenContext::Head | GenContext::Last(_) => {
-                tvd.use_set.insert((term_loc, arg_c));
-            }
-            _ => {}
-        };
-    }
-
-    pub(crate) fn mark_temp_var(&mut self, var_info: &VarInfo) {
-        let chunk_num = term_loc.chunk_num();
-        let var = Var::from(var_info.var_ptr);
-
-        let mut status = self.temp_vars.swap_remove(&var).unwrap_or_else(|| {
-            TempVarStatus {
-                chunk_num,
-                temp_var_data: TempVarData::new(var_info.classify_info.arity),
-            }
-        });
-
-        if let Level::Shallow = var_info.lvl {
-            self.record_temp_info(&mut status, var_info.classify_info.arg_c, term_loc);
-        }
-
-        self.temp_vars.insert(var, status);
-    }
-}
-
-#[derive(Debug)]
-pub(crate) struct UnsafeVarMarker {
-    pub(crate) unsafe_perm_vars: IndexMap<usize, usize>,
-    pub(crate) unsafe_temp_vars: IndexSet<usize>,
-    pub(crate) safe_perm_vars: IndexSet<usize>,
-    pub(crate) safe_temp_vars: IndexSet<usize>,
-    pub(crate) temp_vars_to_perm_vars: IndexMap<usize, usize>,
-}
-
-impl UnsafeVarMarker {
-    pub(crate) fn new() -> Self {
-        UnsafeVarMarker {
-            unsafe_perm_vars: IndexMap::new(),
-            unsafe_temp_vars: IndexSet::new(),
-            safe_perm_vars: IndexSet::new(),
-            safe_temp_vars: IndexSet::new(),
-            temp_vars_to_perm_vars: IndexMap::new(),
-        }
-    }
-
-    pub(crate) fn from_fact_vars(safe_vars: IndexSet<RegType>) -> Self {
-        let mut unsafe_var_marker = Self::new();
-
-        for r in safe_vars {
-            unsafe_var_marker.mark_var_as_safe(r);
-        }
-
-        unsafe_var_marker
-    }
-
-    fn mark_var_as_safe(&mut self, r: RegType) {
-        match r {
-            RegType::Temp(t) => {
-                self.safe_temp_vars.insert(t);
-            }
-            RegType::Perm(p) => {
-                self.safe_perm_vars.insert(p);
-            }
-        };
-    }
-
-    fn mark_var_as_unsafe(&mut self, r: RegType, phase: usize) {
-        match r {
-            RegType::Temp(t) => {
-                self.unsafe_temp_vars.insert(t);
-            }
-            RegType::Perm(p) => {
-                self.unsafe_perm_vars.insert(p, phase);
-            }
-        }
-    }
-
-    // returns true if the instruction at *query_instr cannot be
-    // changed by mark_unsafe_vars.
-    fn mark_safe_vars(&mut self, query_instr: &Instruction) -> bool {
-        match query_instr {
-            &Instruction::PutVariable(r @ RegType::Temp(_), _) |
-            &Instruction::SetVariable(r) => {
-                self.mark_var_as_safe(r);
-                true
-            }
-            &Instruction::PutVariable(RegType::Perm(p), t) => {
-                self.temp_vars_to_perm_vars.insert(t, p);
-                true
-            }
-            &Instruction::CallIs(RegType::Temp(t), ..) => {
-                if let Some(p) = self.temp_vars_to_perm_vars.get(&t) {
-                    self.mark_var_as_safe(RegType::Perm(*p));
-                }
-
-                true
-            }
-            _ => false,
-        }
-    }
-
-    fn mark_phase(&mut self, query_instr: &Instruction, phase: usize) {
-        match query_instr {
-            &Instruction::PutValue(r @ RegType::Perm(_), _) |
-            &Instruction::SetValue(r) => {
-                self.mark_var_as_unsafe(r, phase);
-            }
-            _ => {}
-        }
-    }
-
-    fn mark_unsafe_perm_vars(&mut self, query_instr: &mut Instruction, phase: usize) {
-        match query_instr {
-            &mut Instruction::PutValue(RegType::Perm(p), arg)
-                if !self.safe_perm_vars.contains(&p) => {
-                    if let Some(ph) = self.unsafe_perm_vars.swap_remove(&p) {
-                        if ph == phase {
-                            *query_instr = Instruction::PutUnsafeValue(p, arg);
-                            self.safe_perm_vars.insert(p);
-                        } else {
-                            self.unsafe_perm_vars.insert(p, ph);
-                        }
-                    }
-                }
-            &mut Instruction::SetValue(r @ RegType::Perm(p))
-                if !self.safe_perm_vars.contains(&p) => {
-                    *query_instr = Instruction::SetLocalValue(r);
-
-                    self.safe_perm_vars.insert(p);
-                    self.unsafe_perm_vars.remove(&p);
-                }
-            _ => {}
-        }
-    }
-
-    fn mark_unsafe_temp_vars(&mut self, query_instr: &mut Instruction) {
-        match query_instr {
-            &mut Instruction::SetValue(r @ RegType::Temp(t))
-                if !self.safe_temp_vars.contains(&t) => {
-                    *query_instr = Instruction::SetLocalValue(r);
-
-                    self.safe_temp_vars.insert(t);
-                    self.unsafe_temp_vars.remove(&t);
-                }
-            _ => {
-            }
-        }
-    }
-
-    fn clear_temp_vars(&mut self) {
-        self.safe_temp_vars.clear();
-        self.unsafe_temp_vars.clear();
-        self.temp_vars_to_perm_vars.clear();
-    }
-
-    pub(crate) fn mark_unsafe_instrs(&mut self, code: &mut Code) {
-        if code.is_empty() {
-            return;
-        }
-
-        let mut code_index = 0;
-
-        for phase in 0.. {
-            while code[code_index].is_query_instr() {
-                let query_instr = &mut code[code_index];
-
-                if !self.mark_safe_vars(query_instr) {
-                    self.mark_phase(query_instr, phase);
-                    self.mark_unsafe_temp_vars(query_instr);
-                }
-
-                code_index += 1;
-            }
-
-            while code_index < code.len() && !code[code_index].is_query_instr() {
-                self.mark_safe_vars(&code[code_index]);
-                code_index += 1;
-            }
-
-            self.clear_temp_vars();
-
-            if code_index >= code.len() {
-                break;
-            }
-        }
-
-        code_index = 0;
-
-        for phase in 0.. {
-            while code[code_index].is_query_instr() {
-                let query_instr = &mut code[code_index];
-                self.mark_unsafe_perm_vars(query_instr, phase);
-                code_index += 1;
-            }
-
-            // ensure phase->instruction assignments match those of
-            // the previous for loop.
-            while code_index < code.len() && !code[code_index].is_query_instr() {
-                code_index += 1;
-            }
-
-            if code_index >= code.len() {
-                break;
-            }
-        }
-    }
-}
index 3ed83866d848555b758a1f14b9500a94d3ac2500..627fb4b212628fb281ed8f973866a48cd0b0eb38 100644 (file)
@@ -20,25 +20,23 @@ use std::cell::Cell;
 use std::collections::VecDeque;
 use std::convert::TryFrom;
 use std::fmt;
-use std::ops::AddAssign;
+use std::ops::{AddAssign, Deref, DerefMut};
 use std::path::PathBuf;
 
 use crate::{is_infix, is_postfix};
 
 pub type PredicateKey = (Atom, usize); // name, arity.
 
-pub type Predicate = Vec<PredicateClause>;
-
+/*
 // vars of predicate, toplevel offset.  Vec<Term> is always a vector
 // of vars (we get their adjoining cells this way).
 pub type JumpStub = Vec<Term>;
+*/
 
-#[derive(Debug, Clone)]
+#[derive(Debug)]
 pub enum TopLevel {
-    Fact(Fact), // Term, line_num, col_num
-    Predicate(Predicate),
-    Query(Vec<QueryTerm>),
-    Rule(Rule), // Rule, line_num, col_num
+    Fact(Fact, VarData), // Term, line_num, col_num
+    Rule(Rule, VarData), // Rule, line_num, col_num
 }
 
 #[derive(Debug, Clone, Copy)]
@@ -79,13 +77,30 @@ pub enum CallPolicy {
     Counted,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum ChunkType {
     Head,
     Mid,
     Last,
 }
 
+#[derive(Debug)]
+pub enum RootIterationPolicy {
+    Iterated,
+    NotIterated,
+}
+
+impl RootIterationPolicy {
+    #[inline(always)]
+    pub fn iterable(&self) -> bool {
+        if let RootIterationPolicy::Iterated = self {
+            true
+        } else {
+            false
+        }
+    }
+}
+
 impl ChunkType {
     #[inline(always)]
     pub fn to_gen_context(self, chunk_num: usize) -> GenContext {
@@ -102,47 +117,104 @@ impl ChunkType {
     }
 }
 
+#[derive(Debug)]
+pub enum ChunkedTerms {
+    Branch(Vec<VecDeque<ChunkedTerms>>),
+    Chunk(VecDeque<QueryTerm>),
+}
+
+#[derive(Debug)]
+pub struct ChunkedTermVec {
+    pub chunk_vec: VecDeque<ChunkedTerms>,
+}
+
+impl Deref for ChunkedTermVec {
+    type Target = VecDeque<ChunkedTerms>;
+
+    #[inline(always)]
+    fn deref(&self) -> &Self::Target {
+        &self.chunk_vec
+    }
+}
+
+impl DerefMut for ChunkedTermVec {
+    #[inline(always)]
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.chunk_vec
+    }
+}
+
+impl ChunkedTermVec {
+    #[inline]
+    pub fn new() -> Self {
+        Self { chunk_vec: VecDeque::new() }
+    }
+
+    pub fn reserve_branch(&mut self, capacity: usize) {
+        self.chunk_vec.push_back(ChunkedTerms::Branch(Vec::with_capacity(capacity)));
+    }
+
+    pub fn push_branch_arm(&mut self, branch: VecDeque<ChunkedTerms>) {
+        match self.chunk_vec.back_mut().unwrap() {
+            ChunkedTerms::Branch(branches) => {
+                branches.push(branch);
+            }
+            ChunkedTerms::Chunk(_) => {
+                self.chunk_vec.push_back(ChunkedTerms::Branch(vec![branch]));
+            }
+        }
+    }
+
+    #[inline]
+    pub fn add_chunk(&mut self) {
+        self.chunk_vec.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![])));
+    }
+
+    pub fn push_chunk_term(&mut self, term: QueryTerm) {
+        match self.chunk_vec.back_mut() {
+            Some(ChunkedTerms::Branch(_)) => {
+                self.chunk_vec.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
+            }
+            Some(ChunkedTerms::Chunk(chunk)) => {
+                chunk.push_back(term);
+            }
+            None => {
+                self.chunk_vec.push_back(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
+            }
+        }
+    }
+}
+
 #[derive(Debug)]
 pub enum QueryTerm {
     // register, clause type, subterms, clause call policy.
     Clause(Cell<RegType>, ClauseType, Vec<Term>, CallPolicy),
     Fail,
-    GlobalCut,
-    GetCutPoint(usize),
-    LocalCut(usize),
-    Branch(Vec<Vec<QueryTerm>>),
-    ChunkTypeBoundary(ChunkType),
+    LocalCut(usize), // var_num
+    GlobalCut(usize), // var_num
+    GetCutPoint { var_num: usize, prev_b: bool },
+    GetLevel(usize), // var_num
 }
 
 impl QueryTerm {
-    pub(crate) fn set_call_policy(&mut self, cp: CallPolicy) {
-        match self {
-            &mut QueryTerm::Clause(_, _, _, ref mut clause_cp) => *clause_cp = cp,
-            _ => {}
-        }
-    }
-
     pub(crate) fn arity(&self) -> usize {
         match self {
             &QueryTerm::Clause(_, _, ref subterms, ..) => subterms.len(),
-            &QueryTerm::Cut | &QueryTerm::Branch(_) => 0,
-            &QueryTerm::IfThen(..) => 2,
-            &QueryTerm::Not(_) => 1,
+            &QueryTerm::GetLevel(_) | &QueryTerm::GetCutPoint { .. } => 1,
+            _ => 0,
         }
     }
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug)]
 pub struct Fact {
     pub(crate) head: Term,
-    pub(crate) var_data: VarData,
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug)]
 pub struct Rule {
-    pub(crate) head: (Atom, Vec<Term>, QueryTerm),
-    pub(crate) clauses: Vec<QueryTerm>,
-    pub(crate) var_data: VarData,
+    pub(crate) head: (Atom, Vec<Term>),
+    pub(crate) clauses: ChunkedTermVec,
 }
 
 #[derive(Clone, Debug, Hash)]
@@ -233,29 +305,29 @@ impl ClauseInfo for Rule {
 impl ClauseInfo for PredicateClause {
     fn name(&self) -> Option<Atom> {
         match self {
-            &PredicateClause::Fact(ref term, ..) => term.name(),
+            &PredicateClause::Fact(ref term, ..) => term.head.name(),
             &PredicateClause::Rule(ref rule, ..) => rule.name(),
         }
     }
 
     fn arity(&self) -> usize {
         match self {
-            &PredicateClause::Fact(ref term, ..) => term.arity(),
+            &PredicateClause::Fact(ref term, ..) => term.head.arity(),
             &PredicateClause::Rule(ref rule, ..) => rule.arity(),
         }
     }
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug)]
 pub enum PredicateClause {
-    Fact(Fact),
-    Rule(Rule),
+    Fact(Fact, VarData),
+    Rule(Rule, VarData),
 }
 
 impl PredicateClause {
     pub(crate) fn args(&self) -> Option<&[Term]> {
         match self {
-            PredicateClause::Fact(term, ..) => match term {
+            PredicateClause::Fact(term, ..) => match &term.head {
                 Term::Clause(_, _, args) => Some(&args),
                 _ => None,
             },
index 9760be9ea75dc406fbb5e2a341cd374cf0de99f8..d7f1f2e4cd9c4fedd47cf51fd751bf91a0449109 100644 (file)
@@ -424,7 +424,6 @@ mod tests {
     use super::*;
     use crate::machine::mock_wam::*;
 
-
     #[test]
     fn heap_stackless_iter_tests() {
         let mut wam = MockWAM::new();
index d09211d14845b6b3d32301ab55a8f94dec55e09c..aa93ad29f14c27e0e804236c267692c805a281fa 100644 (file)
@@ -472,7 +472,7 @@ pub struct HCPrinter<'a, Outputter> {
     state_stack: Vec<TokenOrRedirect>,
     toplevel_spec: Option<DirectedOp>,
     last_item_idx: usize,
-    pub var_names: IndexMap<HeapCellValue, Var>,
+    pub var_names: IndexMap<HeapCellValue, VarPtr>,
     pub numbervars_offset: Integer,
     pub numbervars: bool,
     pub quoted: bool,
@@ -803,7 +803,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
         if let Some(var) = self.var_names.get(&addr) {
             read_heap_cell!(addr,
                (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
-                   return Some(var.to_string());
+                   return Some(var.borrow().to_string());
                }
                _ => {
                    self.iter.push_stack(h);
@@ -847,7 +847,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                     // short-circuits handle_heap_term.
                     // self.iter.pop_stack();
 
-                    let var_str = var.to_string();
+                    let var_str = var.borrow().to_string();
 
                     push_space_if_amb!(self, &var_str, {
                         append_str!(self, &var_str);
@@ -862,7 +862,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
                             Some(var) => {
                                 // If the term is bound to a named variable,
                                 // print the variable's name to output.
-                                let var_str = var.to_string();
+                                let var_str = var.borrow().to_string();
 
                                 push_space_if_amb!(self, &var_str, {
                                     append_str!(self, &var_str);
index 529c453cbf3181c07d886abedd173ea8dca6920a..adec2e4ca652f5bd455ddab1f3d212b75c6532ba 100644 (file)
@@ -5,100 +5,40 @@ use crate::parser::ast::*;
 
 use std::cell::Cell;
 use std::collections::VecDeque;
-use std::fmt;
-use std::fmt::Debug;
-use std::hash::{Hash};
 use std::iter::*;
 use std::vec::Vec;
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub(crate) enum VarPtr {
-    ToVar(std::ptr::NonNull<Var>),
-    InSitu(usize),
-}
-
-impl From<&Var> for VarPtr {
-    #[inline]
-    fn from(value: &Var) -> VarPtr {
-        unsafe {
-            VarPtr { ptr: std::ptr::NonNull::new_unchecked(value as *const _ as *mut _) }
-        }
-    }
-}
-
-impl From<VarPtr> for Var {
-    #[inline(always)]
-    fn from(value: VarPtr) -> Var {
-        match value {
-            VarPtr::ToPtr(ptr) => unsafe {
-                (*ptr.ptr.as_ptr()).clone()
-            },
-            VarPtr::InSitu(var_num) => {
-                Var::Generated(var_num)
-            }
-        }
-    }
-}
-
-impl VarPtr {
-    pub(crate) fn set(&mut self, value: Var) {
-        match self {
-            VarPtr::ToVar(ref mut ptr) =>
-                unsafe { *ptr.as_mut() = value },
-            VarPtr::InSitu(_) => {
-            }
-        }
-    }
-}
-
 #[derive(Debug, Clone)]
 pub(crate) enum TermRef<'a> {
     AnonVar(Level),
-    Cut(Level),
-    GetLevel(Level),
     Cons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
-    Fail(Level),
     Literal(Level, &'a Cell<RegType>, &'a Literal),
     Clause(Level, &'a Cell<RegType>, Atom, &'a Vec<Term>),
     PartialString(Level, &'a Cell<RegType>, &'a String, &'a Box<Term>),
     CompleteString(Level, &'a Cell<RegType>, Atom),
-    Var(Level, &'a Cell<VarReg>, Var),
-    InitialBranch(Level),
-    MiddleBranch(Level),
-    FinalBranch(Level),
+    Var(Level, &'a Cell<VarReg>, VarPtr),
 }
 
+/*
 impl<'a> TermRef<'a> {
-    pub(crate) fn level(self) -> Level {
+    pub(crate) fn level(&self) -> Level {
         match self {
             TermRef::AnonVar(lvl) |
             TermRef::Cons(lvl, ..) |
-            TermRef::Cut(lvl) |
-            TermRef::GetLevel(lvl) |
             TermRef::Literal(lvl, ..) |
             TermRef::Var(lvl, ..) |
             TermRef::Clause(lvl, ..) |
             TermRef::CompleteString(lvl, ..) |
-            TermRef::PartialString(lvl, ..) |
-            TermRef::InitialBranch(lvl) |
-            TermRef::MiddleBranch(lvl) |
-            TermRef::FinalBranch(lvl) |
-            TermRef::Fail(lvl) => lvl,
+            TermRef::PartialString(lvl, ..) => *lvl,
         }
     }
 }
+*/
 
 #[derive(Debug)]
 pub(crate) enum TermIterState<'a> {
     AnonVar(Level),
     Clause(Level, usize, &'a Cell<RegType>, Atom, &'a Vec<Term>),
-    Cut(Level),
-    Fail(Level),
-    GetLevel(Level),
-    InitialBranch(Level, &'a Vec<QueryTerm>),
-    MiddleBranch(Level, &'a Vec<QueryTerm>),
-    FinalBranch(Level, &'a Vec<QueryTerm>),
-    Sequence(Level, &'a Vec<QueryTerm>),
     Literal(Level, &'a Cell<RegType>, &'a Literal),
     InitialCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
     FinalCons(Level, &'a Cell<RegType>, &'a Term, &'a Term),
@@ -125,7 +65,7 @@ impl<'a> TermIterState<'a> {
             Term::CompleteString(cell, atom) => {
                 TermIterState::CompleteString(lvl, cell, *atom)
             }
-            Term::Var(cell, var) => TermIterState::Var(lvl, cell, VarPtr::from(var)),
+            Term::Var(cell, var_ptr) => TermIterState::Var(lvl, cell, var_ptr.clone()),
         }
     }
 }
@@ -140,6 +80,7 @@ impl<'a> QueryIterator<'a> {
         self.state_stack.push(TermIterState::subterm_to_state(lvl, term));
     }
 
+    /*
     fn from_rule_head_clause(terms: &'a Vec<Term>) -> Self {
         let state_stack = terms
             .iter()
@@ -149,6 +90,7 @@ impl<'a> QueryIterator<'a> {
 
         QueryIterator { state_stack }
     }
+    */
 
     fn from_term(term: &'a Term) -> Self {
         let state = match term {
@@ -165,7 +107,7 @@ impl<'a> QueryIterator<'a> {
                 *name,
                 terms,
             ),
-            Term::Var(cell, var) => TermIterState::Var(Level::Root, cell, VarPtr::from(var)),
+            Term::Var(cell, var_ptr) => TermIterState::Var(Level::Root, cell, var_ptr.clone()),
         };
 
         QueryIterator {
@@ -181,36 +123,12 @@ impl<'a> QueryIterator<'a> {
             &QueryTerm::Clause(ref cell, ref ct, ref terms, _) => {
                 self.state_stack.push(TermIterState::Clause(lvl, 0, cell, ct.name(), terms));
             }
-            &QueryTerm::Cut => {
-                self.state_stack.push(TermIterState::Cut(lvl));
-            }
-            &QueryTerm::Not(ref terms) => {
-                self.state_stack.push(TermIterState::Fail(lvl));
-                self.state_stack.push(TermIterState::Cut(lvl));
-                self.state_stack.push(TermIterState::Sequence(lvl, terms));
-            }
-            &QueryTerm::IfThen(ref if_terms, ref then_terms) => {
-                self.state_stack.push(TermIterState::Sequence(lvl, then_terms));
-                self.state_stack.push(TermIterState::Cut(lvl));
-                self.state_stack.push(TermIterState::Sequence(lvl, if_terms));
-                self.state_stack.push(TermIterState::GetLevel(lvl));
-            }
-            &QueryTerm::Branch(ref branches) => {
-                let len = branches.len();
-                self.state_stack.push(TermIterState::FinalBranch(lvl, &branches[len - 1]));
-
-                self.state_stack.extend(branches[1 .. len - 1]
-                    .iter()
-                    .rev()
-                    .map(|t| TermIterState::MiddleBranch(lvl, t)),
-                );
-
-                self.state_stack.push(TermIterState::InitialBranch(lvl, &branches[0]));
+            _ => {
             }
         }
     }
 
-    fn new(term: &'a QueryTerm) -> Self {
+    pub fn new(term: &'a QueryTerm) -> Self {
         let mut iter = QueryIterator { state_stack: vec![] };
         iter.extend_state(Level::Root, term);
         iter
@@ -273,34 +191,8 @@ impl<'a> Iterator for QueryIterator<'a> {
                 TermIterState::Literal(lvl, cell, constant) => {
                     return Some(TermRef::Literal(lvl, cell, constant));
                 }
-                TermIterState::Var(lvl, cell, var) => {
-                    return Some(TermRef::Var(lvl, cell, Var::from(var)));
-                }
-                TermIterState::Cut(lvl) => {
-                    return Some(TermRef::Cut(lvl));
-                }
-                TermIterState::GetLevel(lvl) => {
-                    return Some(TermRef::GetLevel(lvl));
-                }
-                TermIterState::InitialBranch(lvl, ref branch) => {
-                    self.state_stack.push(TermIterState::Sequence(lvl, branch));
-                    return Some(TermRef::InitialBranch(lvl));
-                }
-                TermIterState::MiddleBranch(lvl, ref branch) => {
-                    self.state_stack.push(TermIterState::Sequence(lvl, branch));
-                    return Some(TermRef::MiddleBranch(lvl));
-                }
-                TermIterState::FinalBranch(lvl, ref branch) => {
-                    self.state_stack.push(TermIterState::Sequence(lvl, branch));
-                    return Some(TermRef::FinalBranch(lvl));
-                }
-                TermIterState::Sequence(lvl, ref terms) => {
-                    for term in branch.iter().rev() {
-                        self.extend_state(lvl, term);
-                    }
-                }
-                TermIterState::Fail(lvl) => {
-                    return Some(TermRef::Fail(lvl));
+                TermIterState::Var(lvl, cell, var_ptr) => {
+                    return Some(TermRef::Var(lvl, cell, var_ptr));
                 }
             };
         }
@@ -312,7 +204,7 @@ impl<'a> Iterator for QueryIterator<'a> {
 #[derive(Debug)]
 pub(crate) struct FactIterator<'a> {
     state_queue: VecDeque<TermIterState<'a>>,
-    iterable_root: bool,
+    iterable_root: RootIterationPolicy,
 }
 
 impl<'a> FactIterator<'a> {
@@ -329,11 +221,11 @@ impl<'a> FactIterator<'a> {
 
         FactIterator {
             state_queue,
-            iterable_root: false,
+            iterable_root: RootIterationPolicy::NotIterated,
         }
     }
 
-    fn new(term: &'a Term, iterable_root: bool) -> Self {
+    fn new(term: &'a Term, iterable_root: RootIterationPolicy) -> Self {
         let states = match term {
             Term::AnonVar => {
                 vec![TermIterState::AnonVar(Level::Root)]
@@ -365,8 +257,8 @@ impl<'a> FactIterator<'a> {
             Term::Literal(cell, constant) => {
                 vec![TermIterState::Literal(Level::Root, cell, constant)]
             }
-            Term::Var(cell, var) => {
-                vec![TermIterState::Var(Level::Root, cell, VarPtr::from(var))]
+            Term::Var(cell, var_ptr) => {
+                vec![TermIterState::Var(Level::Root, cell, var_ptr.clone())]
             }
         };
 
@@ -392,7 +284,7 @@ impl<'a> Iterator for FactIterator<'a> {
                     }
 
                     match lvl {
-                        Level::Root if !self.iterable_root => continue,
+                        Level::Root if !self.iterable_root.iterable() => continue,
                         _ => return Some(TermRef::Clause(lvl, cell, name, child_terms)),
                     };
                 }
@@ -412,8 +304,8 @@ impl<'a> Iterator for FactIterator<'a> {
                 TermIterState::Literal(lvl, cell, constant) => {
                     return Some(TermRef::Literal(lvl, cell, constant))
                 }
-                TermIterState::Var(lvl, cell, var) => {
-                    return Some(TermRef::Var(lvl, cell, Var::from(var)));
+                TermIterState::Var(lvl, cell, var_ptr) => {
+                    return Some(TermRef::Var(lvl, cell, var_ptr));
                 }
                 _ => {}
             }
@@ -427,143 +319,130 @@ pub(crate) fn post_order_iter<'a>(term: &'a Term) -> QueryIterator<'a> {
     QueryIterator::from_term(term)
 }
 
-pub(crate) fn breadth_first_iter<'a>(term: &'a Term, iterable_root: bool) -> FactIterator<'a> {
+pub(crate) fn breadth_first_iter<'a>(term: &'a Term, iterable_root: RootIterationPolicy) -> FactIterator<'a> {
     FactIterator::new(term, iterable_root)
 }
 
-/*
-#[derive(Debug)]
-pub(crate) enum ChunkedTerm<'a> {
-    HeadClause(Atom, &'a Vec<Term>),
-    BodyTerm(&'a QueryTerm),
-}
-
-pub(crate) fn query_term_post_order_iter<'a>(query_term: &'a QueryTerm) -> QueryIterator<'a> {
-    QueryIterator::new(query_term)
+#[derive(Debug, Copy, Clone)]
+enum ClauseIteratorState<'a> {
+    RemainingChunks(&'a VecDeque<ChunkedTerms>, usize),
+    RemainingBranches(&'a Vec<VecDeque<ChunkedTerms>>, usize),
 }
 
-impl<'a> ChunkedTerm<'a> {
-    pub(crate) fn post_order_iter(&self) -> QueryIterator<'a> {
-        match self {
-            &ChunkedTerm::BodyTerm(qt) => QueryIterator::new(qt),
-            &ChunkedTerm::HeadClause(_, terms) => QueryIterator::from_rule_head_clause(terms),
-        }
-    }
+#[derive(Debug, Clone)]
+pub(crate) enum ClauseItem<'a> {
+    FirstBranch(usize),
+    NextBranch,
+    BranchEnd(usize),
+    Chunk(&'a VecDeque<QueryTerm>),
 }
 
-pub(crate) struct ChunkedIterator<'a> {
-    pub(crate) chunk_num: usize,
-    iter: Box<dyn Iterator<Item = ChunkedTerm<'a>> + 'a>,
+#[derive(Debug)]
+pub(crate) struct ClauseIterator<'a> {
+    state_stack: Vec<ClauseIteratorState<'a>>,
+    remaining_chunks_on_stack: usize,
 }
 
-impl<'a> fmt::Debug for ChunkedIterator<'a> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt.debug_struct("ChunkedIterator")
-            .field("chunk_num", &self.chunk_num)
-            // Hacky solution.
-            .field("iter", &"Box<dyn Iterator<Item = ChunkedTerm<'a>> + 'a>")
-            .finish()
+fn state_from_chunked_terms<'a>(chunk_vec: &'a VecDeque<ChunkedTerms>) -> ClauseIteratorState<'a> {
+    if chunk_vec.len() == 1 {
+        if let Some(ChunkedTerms::Branch(ref branches)) = chunk_vec.front() {
+            return ClauseIteratorState::RemainingBranches(branches, 0);
+        }
     }
+
+    ClauseIteratorState::RemainingChunks(chunk_vec, 0)
 }
 
-type ChunkedIteratorItem<'a> = (usize, usize, Vec<ChunkedTerm<'a>>);
-type RuleBodyIteratorItem<'a> = (usize, usize, Vec<&'a QueryTerm>);
-
-impl<'a> ChunkedIterator<'a> {
-    pub(crate) fn rule_body_iter(self) -> Box<dyn Iterator<Item = RuleBodyIteratorItem<'a>> + 'a> {
-        Box::new(self.filter_map(|(cn, lt_arity, terms)| {
-            let filtered_terms: Vec<_> = terms
-                .into_iter()
-                .filter_map(|ct| match ct {
-                    ChunkedTerm::BodyTerm(qt) => Some(qt),
-                    _ => None,
-                })
-                .collect();
-
-            if filtered_terms.is_empty() {
-                None
-            } else {
-                Some((cn, lt_arity, filtered_terms))
+impl<'a> ClauseIterator<'a> {
+    pub fn new(clauses: &'a ChunkedTermVec) -> Self {
+        match state_from_chunked_terms(&clauses.chunk_vec) {
+            state @ ClauseIteratorState::RemainingBranches(..) => {
+                Self {
+                    state_stack: vec![state],
+                    remaining_chunks_on_stack: 0,
+                }
+            }
+            state @ ClauseIteratorState::RemainingChunks(..) => {
+                Self {
+                    state_stack: vec![state],
+                    remaining_chunks_on_stack: 1,
+                }
             }
-        }))
-    }
-
-    pub(crate) fn from_rule_body(p1: &'a QueryTerm, clauses: &'a Vec<QueryTerm>) -> Self {
-        let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
-        let iter = inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t)));
-
-        ChunkedIterator {
-            chunk_num: 0,
-            iter: Box::new(iter),
         }
     }
 
-    pub(crate) fn from_rule(rule: &'a Rule) -> Self {
-        let &Rule {
-            head: (ref name, ref args, ref p1),
-            ref clauses,
-            ..
-        } = rule;
-
-        let iter = once(ChunkedTerm::HeadClause(name.clone(), args));
-        let inner_iter = Box::new(once(ChunkedTerm::BodyTerm(p1)));
-        let iter = iter.chain(inner_iter.chain(clauses.iter().map(|t| ChunkedTerm::BodyTerm(t))));
-
-        ChunkedIterator {
-            chunk_num: 0,
-            iter: Box::new(iter),
-        }
+    #[inline(always)]
+    pub fn in_tail_position(&self) -> bool {
+        self.remaining_chunks_on_stack == 0
     }
 
-    fn take_chunk(&mut self, term: ChunkedTerm<'a>) -> (usize, usize, Vec<ChunkedTerm<'a>>) {
-        let mut arity = 0;
-        let mut item = Some(term);
-        let mut result = Vec::new();
+    fn branch_end_depth(&mut self) -> usize {
+        let mut depth = 1;
 
-        while let Some(term) = item {
-            match term {
-                ChunkedTerm::HeadClause(_, terms) => {
-                    result.push(term);
-                }
-                ChunkedTerm::BodyTerm(&QueryTerm::Cut) => {
-                    result.push(term);
-                }
-                ChunkedTerm::BodyTerm(&QueryTerm::Clause(_, ClauseType::Inlined(_), ..)) => {
-                    result.push(term);
-                }
-                ChunkedTerm::BodyTerm(&QueryTerm::Clause(
-                    _,
-                    ClauseType::CallN(_),
-                    ref subterms,
-                    _,
-                )) => {
-                    result.push(term);
-                    arity = subterms.len() + 1;
-                    break;
+        while let Some(state) = self.state_stack.pop() {
+            match state {
+                ClauseIteratorState::RemainingBranches(terms, focus) if terms.len() == focus => {
+                    depth += 1;
                 }
-                ChunkedTerm::BodyTerm(qt) => {
-                    result.push(term);
-                    arity = qt.arity();
+                _ => {
+                    self.state_stack.push(state);
                     break;
                 }
-            };
-
-            item = self.iter.next();
+            }
         }
 
-        let chunk_num = self.chunk_num;
-        self.chunk_num += 1;
-
-        (chunk_num, arity, result)
+        depth
     }
 }
 
-impl<'a> Iterator for ChunkedIterator<'a> {
-    // the chunk number, last term arity, and vector of references.
-    type Item = ChunkedIteratorItem<'a>;
+impl<'a> Iterator for ClauseIterator<'a> {
+    type Item = ClauseItem<'a>;
 
     fn next(&mut self) -> Option<Self::Item> {
-        self.iter.next().map(|term| self.take_chunk(term))
+        while let Some(state) = self.state_stack.pop() {
+            match state {
+                ClauseIteratorState::RemainingChunks(chunks, focus) if focus < chunks.len() => {
+                    if focus + 1 < chunks.len() {
+                        self.state_stack.push(ClauseIteratorState::RemainingChunks(chunks, focus + 1));
+                    } else {
+                        self.remaining_chunks_on_stack -= 1;
+                    }
+
+                    match &chunks[focus] {
+                        ChunkedTerms::Branch(branches) => {
+                            self.state_stack.push(ClauseIteratorState::RemainingBranches(branches, 0));
+                        }
+                        ChunkedTerms::Chunk(chunk) => {
+                            return Some(ClauseItem::Chunk(chunk));
+                        }
+                    }
+                }
+                ClauseIteratorState::RemainingChunks(chunks, focus) => {
+                    debug_assert_eq!(chunks.len(), focus);
+                }
+                ClauseIteratorState::RemainingBranches(branches, focus) if focus < branches.len() => {
+                    self.state_stack.push(ClauseIteratorState::RemainingBranches(&branches, focus + 1));
+                    let state = state_from_chunked_terms(&branches[focus]);
+
+                    if let ClauseIteratorState::RemainingChunks(..) = &state {
+                        self.remaining_chunks_on_stack += 1;
+                    }
+
+                    self.state_stack.push(state);
+
+                    return if focus == 0 {
+                        Some(ClauseItem::FirstBranch(branches.len()))
+                    } else {
+                        Some(ClauseItem::NextBranch)
+                    };
+                }
+                ClauseIteratorState::RemainingBranches(branches, focus) => {
+                    debug_assert_eq!(branches.len(), focus);
+                    return Some(ClauseItem::BranchEnd(self.branch_end_depth()));
+                }
+            }
+        }
+
+        None
     }
 }
-*/
index 45dc23856cd9fa0dd73c4f00c4df6c54707275e9..36f7a45bf096174c3198ea6d7c6f6dcf0a457bcf 100644 (file)
@@ -16,7 +16,7 @@ mod arithmetic;
 pub mod codegen;
 mod debray_allocator;
 mod ffi;
-mod fixtures;
+mod variable_records;
 mod forms;
 mod heap_iter;
 pub mod heap_print;
index 0005d39570a652255e61a25a3776a4e95286ca7f..1c183a0c88aa88bdf43223bb2b927d24e56250ee 100644 (file)
@@ -218,13 +218,13 @@ fail :- '$fail'.
 %% \+(Goal)
 %
 % True iff Goal fails
-\+ G :- call(G), !, false.
+\+ G :- call(G), !, '$fail'.
 \+ _.
 
 %% \=(?X, ?Y)
 %
 % True iff X and Y can't be unified
-X \= X :- !, false.
+X \= X :- !, '$fail'.
 _ \= _.
 
 
index 32ad2ff9335861b0bbc257004e95fcf3c3ae9217..be1cd532756c8d654f54f83b74e4771e390448f1 100644 (file)
@@ -513,10 +513,12 @@ portray_clause(Stream, Term) :-
         phrase_to_stream(portray_clause_(Term), Stream),
         flush_output(Stream).
 
+% called once.
 portray_clause_(Term) -->
         { unique_variable_names(Term, VNs) },
         portray_(Term, VNs), ".\n".
 
+% mysteriously called twice, the second time with the truncated B3.
 unique_variable_names(Term, VNs) :-
         term_variables(Term, Vs),
         foldl(var_name, Vs, VNs, 0, _).
index 896d6bff5a97115116ffefacf0f6aa5564788900..5c35822e67ea1b072cb5935be68b6283888e6a6b 100644 (file)
@@ -541,6 +541,7 @@ open_file(Path, Stream) :-
             )
     ).
 
+
 use_module(Module, Exports, Evacuable) :-
     (  var(Module) ->
        instantiation_error(load/1)
@@ -562,12 +563,11 @@ use_module(Module, Exports, Evacuable) :-
           stream_property(Stream, file_name(PathFileName)),
           file_load(Stream, PathFileName, Subevacuable),
           '$use_module'(Evacuable, Subevacuable, Exports)
-       ;  type_error(atom, Library, load/1)
+       ;  type_error(atom, Module, load/1)
        )
     ).
 
 
-
 check_predicate_property(meta_predicate, Module, Name, Arity, MetaPredicateTerm) :-
     '$meta_predicate_property'(Module, Name, Arity, MetaPredicateTerm).
 check_predicate_property(built_in, _, Name, Arity, built_in) :-
index fcda8710045e46cc205bf931e9ee964040c3478e..1244eb205e5b6f00759b8645db24c86b71498c6f 100644 (file)
@@ -23,13 +23,9 @@ fn capture_offset(line: &Instruction, index: usize, stack: &mut Vec<usize>) -> b
         {
             stack.push(index + offset);
         }
-        &Instruction::JmpByCall(_, offset, _) => {
+        &Instruction::JmpByCall(offset) => {
             stack.push(index + offset);
         }
-        &Instruction::JmpByExecute(_, offset, _) => {
-            stack.push(index + offset);
-            return true;
-        }
         &Instruction::Proceed => {
             return true;
         }
index 428e29527718a014c91f15f2f060be57f38377fa..0faf34c33455ec2d61c5dea4b901a660ccd4df2a 100644 (file)
@@ -44,62 +44,6 @@ pub(super) fn bootstrapping_compile(
     Ok(())
 }
 
-// throw errors if declaration or query found.
-pub(super) fn compile_relation(
-    cg: &mut CodeGenerator,
-    tl: &TopLevel,
-) -> Result<Code, CompilationError> {
-    match tl {
-        &TopLevel::Query(_) => Err(CompilationError::ExpectedRel),
-        &TopLevel::Predicate(ref clauses) => cg.compile_predicate(&clauses),
-        &TopLevel::Fact(ref fact, ..) => cg.compile_fact(fact),
-        &TopLevel::Rule(ref rule, ..) => cg.compile_rule(rule),
-    }
-}
-
-/*
-pub(super) fn compile_appendix(
-    code: &mut Code,
-    mut queue: VecDeque<TopLevel>,
-    jmp_by_locs: Vec<usize>,
-    non_counted_bt: bool,
-    atom_tbl: &mut AtomTable,
-) -> Result<(), CompilationError> {
-    let mut jmp_by_locs = VecDeque::from(jmp_by_locs);
-
-    while let Some(jmp_by_offset) = jmp_by_locs.pop_front() {
-        let code_len = code.len();
-
-        match &mut code[jmp_by_offset] {
-            &mut Instruction::JmpByCall(_, ref mut offset, ..) |
-            &mut Instruction::JmpByExecute(_, ref mut offset, ..) => {
-                *offset = code_len - jmp_by_offset;
-            }
-            _ => {
-                unreachable!()
-            }
-        }
-
-        // false because the inner predicate is a one-off, hence not extensible.
-        let settings = CodeGenSettings {
-            global_clock_tick: None,
-            is_extensible: false,
-            non_counted_bt,
-        };
-
-        let mut cg = CodeGenerator::new(atom_tbl, settings);
-
-        let tl = queue.pop_front().unwrap();
-        let decl_code = compile_relation(&mut cg, &tl)?;
-
-        jmp_by_locs.extend(cg.jmp_by_locs.into_iter().map(|offset| offset + code.len()));
-        code.extend(decl_code.into_iter());
-    }
-
-    Ok(())
-}
-*/
-
 fn lower_bound_of_target_clause(skeleton: &PredicateSkeleton, target_pos: usize) -> usize {
     if target_pos == 0 {
         return 0;
@@ -1351,17 +1295,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
             settings,
         );
 
-        let mut clause_code = cg.compile_predicate(&vec![clause])?;
-
-        /*
-        compile_appendix(
-            &mut clause_code,
-            queue,
-            cg.jmp_by_locs,
-            settings.non_counted_bt,
-            cg.atom_tbl,
-        )?;
-        */
+        let clause_code = cg.compile_predicate(vec![clause])?;
 
         Ok(StandaloneCompileResult {
             clause_code,
@@ -1389,24 +1323,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
             clauses.push(self.try_term_to_tl(term, &mut preprocessor)?);
         }
 
-        // let queue = preprocessor.parse_queue(self)?;
-
         let mut cg = CodeGenerator::new(
             &mut LS::machine_st(&mut self.payload).atom_tbl,
             settings,
         );
 
-        let mut code = cg.compile_predicate(&clauses)?;
-
-        /*
-        compile_appendix(
-            &mut code,
-            queue,
-            cg.jmp_by_locs,
-            settings.non_counted_bt,
-            cg.atom_tbl,
-        )?;
-         */
+        let mut code = cg.compile_predicate(clauses)?;
 
         if settings.is_extensible {
             let mut clause_clause_locs = VecDeque::new();
index 98875bc81808f42ba93c168f69602239b383f459..1b65ef9ee5efab1a4111c4668f286b7503bac83f 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
 ================================================================================
 
@@ -9,7 +8,6 @@ paper "Compiling Large Disjunctions" to Scryer Prolog.
  */
 
 use crate::atom_table::*;
-use crate::fixtures::VariableFixtures;
 use crate::forms::*;
 use crate::instructions::*;
 use crate::iterators::*;
@@ -18,16 +16,18 @@ use crate::machine::machine_errors::CompilationError;
 use crate::machine::preprocessor::*;
 use crate::parser::ast::*;
 use crate::parser::rug::Rational;
+use crate::variable_records::*;
 
 use indexmap::{IndexMap, IndexSet};
 
 use std::cell::Cell;
 use std::cmp::Ordering;
+use std::collections::VecDeque;
 use std::hash::{Hash, Hasher};
 use std::ops::{Deref, DerefMut};
 
-#[derive(Debug, Clone)]
-struct BranchNumber {
+#[derive(Debug, Clone)] //, PartialOrd, PartialEq, Eq, Hash)]
+pub struct BranchNumber {
     branch_num: Rational,
     delta: Rational,
 }
@@ -35,7 +35,7 @@ struct BranchNumber {
 impl Default for BranchNumber {
     fn default() -> Self {
         Self {
-            branch_num: Rational::from(1 << 63),
+            branch_num: Rational::from(1usize << 63),
             delta: Rational::from(1),
         }
     }
@@ -87,9 +87,10 @@ impl BranchNumber {
     }
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct VarInfo {
     var_ptr: VarPtr,
+    chunk_type: ChunkType,
     classify_info: ClassifyInfo,
     lvl: Level,
 }
@@ -102,6 +103,11 @@ pub struct ChunkInfo {
     vars: Vec<VarInfo>,
 }
 
+#[derive(Debug)]
+pub struct BranchArm {
+    pub arm_terms: Vec<QueryTerm>,
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct BranchInfo {
     branch_num: BranchNumber,
@@ -114,7 +120,7 @@ impl BranchInfo {
     }
 }
 
-type BranchMapInt = IndexMap<Var, Vec<BranchInfo>>;
+type BranchMapInt = IndexMap<VarPtr, Vec<BranchInfo>>;
 
 #[derive(Debug, Clone)]
 pub struct BranchMap(BranchMapInt);
@@ -145,82 +151,77 @@ pub struct ClassifyInfo {
 
 enum TraversalState {
     // construct a QueryTerm::Branch with number of disjuncts, reset
-    // the chunk type to that of the chunk preceding the disjunct.
-    BuildDisjunct(ChunkType, usize),
+    // the chunk type to that of the chunk preceding the disjunct and the chunk_num.
+    BuildDisjunct(usize),
     // add the last disjunct to a QueryTerm::Branch, continuing from
     // where it leaves off.
     BuildFinalDisjunct(usize),
     Fail,
-    GetCutPoint(usize),
-    LocalCut(usize),
+    GetCutPoint{ var_num: usize, prev_b: bool },
+    Cut { var_num: usize, is_global: bool },
     ResetCallPolicy(CallPolicy),
     Term(Term),
-    AddBranchNum(BranchNumber), // set current_branch_number, add it to the root set
-    RemoveBranchNum, // remove latest branch number from the root set
-    RepBranchNum(BranchNumber), // replace current_branch_number and the latest in the root set
-    IncrChunkNum, // increment self.current_chunk_number
-    SetLastChunkType, // consider remaining terms as belonging to a last chunk
-}
-
-impl Term {
-    #[inline]
-    fn is_var(&self) -> bool {
-        if let Term::Var(..) = self {
-            true
-        } else {
-            false
-        }
-    }
-
-    #[inline]
-    fn is_compound(&self) -> bool {
-        match self {
-            Term::Clause(..) | Term::Cons(..) => true,
-            _ => false,
-        }
-    }
+    RemoveBranchNum, // pop the current_branch_num and from the root set.
+    AddBranchNum(BranchNumber), // set current_branch_num, add it to the root set
+    RepBranchNum(BranchNumber), // replace current_branch_num and the latest in the root set
+    // SetChunkType(ChunkType), // consider remaining terms as belonging to a last chunk
 }
 
+#[derive(Debug)]
 pub struct VariableClassifier {
     call_policy: CallPolicy,
     current_branch_num: BranchNumber,
     current_chunk_num: usize,
+    current_chunk_type: ChunkType,
     branch_map: BranchMap,
     var_num: usize,
     root_set: RootSet,
+    global_cut_var_num: Option<usize>,
 }
 
-#[derive(Debug)]
-pub enum VarClassification {
-    Void,
-    Temp,
-    Perm,
+#[derive(Debug, Default)]
+pub struct VarData {
+    pub records: VariableRecords,
+    pub global_cut_var_num: Option<usize>,
+    pub allocates: bool,
 }
 
-#[derive(Clone, Debug)]
-pub struct VarRecord {
-    pub classification: VarClassification,
-    pub chunk_occurrences: Vec<usize>,
-    pub num_occurrences: usize,
-}
+impl VarData {
+    fn emit_initial_get_level(&mut self, build_stack: &mut ChunkedTermVec) {
+        let global_cut_var_num =
+            if let &Some(global_cut_var_num) = &self.global_cut_var_num {
+                match &self.records[global_cut_var_num].allocation {
+                    VarAlloc::Perm(..) => Some(global_cut_var_num),
+                    VarAlloc::Temp { term_loc, .. } if term_loc.chunk_num() > 0 => {
+                        Some(global_cut_var_num)
+                    }
+                    _ => None
+                }
+            } else {
+                None
+            };
 
-impl Default for VarRecord {
-    fn default() -> Self {
-        VarRecord {
-            classification: VarClassification::Void,
-            chunk_occurrences: vec![],
-            num_occurrences: 0,
+        if let Some(global_cut_var_num) = global_cut_var_num {
+            let term = QueryTerm::GetLevel(global_cut_var_num);
+            self.records[global_cut_var_num].allocation = VarAlloc::Perm(0, PermVarAllocation::Pending);
+
+            match build_stack.front_mut() {
+                Some(ChunkedTerms::Branch(_)) => {
+                    build_stack.push_front(ChunkedTerms::Chunk(VecDeque::from(vec![term])));
+                }
+                Some(ChunkedTerms::Chunk(chunk)) => {
+                    chunk.push_front(term);
+                }
+                None => {
+                    unreachable!()
+                }
+            }
         }
     }
 }
 
-pub struct VarData {
-    pub records:  Vec<VarRecord>,
-    pub fixtures: VariableFixtures,
-}
-
 pub type ClassifyFactResult = (Term, VarData);
-pub type ClassifyRuleResult = (Term, Vec<QueryTerm>, VarData);
+pub type ClassifyRuleResult = (Term, ChunkedTermVec, VarData);
 
 fn merge_branch_seq<Iter: Iterator<Item = BranchInfo>>(branches: Iter) -> BranchInfo {
     let mut branch_info = BranchInfo::new(BranchNumber::default());
@@ -228,6 +229,7 @@ fn merge_branch_seq<Iter: Iterator<Item = BranchInfo>>(branches: Iter) -> Branch
     for mut branch in branches {
         branch_info.branch_num = branch.branch_num;
 
+        /*
         if let Some(last_chunk) = branch_info.chunks.last_mut() {
             if let Some(first_moved_chunk) = branch.chunks.first_mut() {
                 if last_chunk.chunk_num == first_moved_chunk.chunk_num {
@@ -238,6 +240,7 @@ fn merge_branch_seq<Iter: Iterator<Item = BranchInfo>>(branches: Iter) -> Branch
                 }
             }
         }
+        */
 
         branch_info.chunks.extend(branch.chunks.drain(..));
     }
@@ -248,82 +251,37 @@ fn merge_branch_seq<Iter: Iterator<Item = BranchInfo>>(branches: Iter) -> Branch
     branch_info
 }
 
-fn flatten_into_disjunct(build_stack: &mut Vec<QueryTerm>, preceding_len: usize) {
-    let iter = build_stack.drain(preceding_len + 1 ..);
+fn flatten_into_disjunct(build_stack: &mut ChunkedTermVec, preceding_len: usize) {
+    let branch_vec = build_stack.drain(preceding_len + 1 ..).collect();
 
-    if let QueryTerm::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] {
-        disjuncts.push(iter.collect());
+    if let ChunkedTerms::Branch(ref mut disjuncts) = &mut build_stack[preceding_len] {
+        disjuncts.push(branch_vec);
     } else {
         unreachable!();
     }
 }
 
-fn term_in_other_chunk(term: &Term) -> Option<bool> {
-    match term {
-        Term::Clause(_, name, terms) => Some(!ClauseType::is_inbuilt(*name, terms.len())),
-        Term::Literal(_, Literal::Atom(atom!("!")) | Literal::Char('!')) => Some(false),
-        Term::Literal(_, Literal::Atom(name)) => Some(!ClauseType::is_inbuilt(*name, 0)),
-        Term::Var(..) => Some(true),
-        _ => None,
-    }
-}
-
-// returns true if SetLastChunkType was pushed.
-// expects that iter iterates over a conjunct of Terms in reverse order.
-fn insert_set_last_chunk_type(
-    state_stack: &mut Vec<TraversalState>,
-    mut iter: impl Iterator<Item = TraversalState>,
-) -> bool {
-    let beg = state_stack.len();
-
-    let mut will_break = false;
-    let mut last_chunk_delim = beg;
-
-    while let Some(traversal_st) = iter.next() {
-        match traversal_st {
-            TraversalState::Term(term) => {
-                will_break = false;
-
-                match term_in_other_chunk(&term) {
-                    Some(true) if last_chunk_delim > beg => will_break = true,
-                    Some(_) => last_chunk_delim += 1,
-                    None => will_break = true,
-                }
-
-                if will_break {
-                    // recall that iter iterates in reverse order.
-                    // therefore this is the correct push order.
-                    state_stack.push(TraversalState::SetLastChunkType);
-                    state_stack.push(traversal_st);
-
-                    break;
-                }
-            }
-            _ => {
-                state_stack.push(traversal_st);
-            }
-        }
-    }
-
-    state_stack.extend(iter);
-    will_break
-}
-
 impl VariableClassifier {
     pub fn new(call_policy: CallPolicy) -> Self {
         Self {
             call_policy,
             current_branch_num: BranchNumber::default(),
             current_chunk_num: 0,
+            current_chunk_type: ChunkType::Head,
             branch_map: BranchMap(BranchMapInt::new()),
             root_set: RootSet::new(),
             var_num: 0,
+            global_cut_var_num: None,
         }
     }
 
     pub fn classify_fact(mut self, term: Term) -> Result<ClassifyFactResult, CompilationError> {
         self.classify_head_variables(&term)?;
-        Ok((term, self.branch_map.separate_and_classify_variables(self.var_num)))
+        Ok((term, self.branch_map.separate_and_classify_variables(
+            self.var_num,
+            self.global_cut_var_num,
+            self.current_chunk_num,
+        )))
     }
 
     pub fn classify_rule<'a, LS: LoadState<'a>>(
@@ -333,9 +291,21 @@ impl VariableClassifier {
         body: Term,
     ) -> Result<ClassifyRuleResult, CompilationError> {
         self.classify_head_variables(&head)?;
-        let query_terms = self.classify_body_variables(loader, body)?;
+        self.root_set.insert(self.current_branch_num.clone());
+
+        let mut query_terms = self.classify_body_variables(loader, body)?;
 
-        Ok((head, query_terms, self.branch_map.separate_and_classify_variables(self.var_num)))
+        self.merge_branches();
+
+        let mut var_data = self.branch_map.separate_and_classify_variables(
+            self.var_num,
+            self.global_cut_var_num,
+            self.current_chunk_num,
+        );
+
+        var_data.emit_initial_get_level(&mut query_terms);
+
+        Ok((head, query_terms, var_data))
     }
 
     fn merge_branches(&mut self) {
@@ -359,24 +329,49 @@ impl VariableClassifier {
         }
     }
 
-    fn probe_body_term(&mut self, term: &Term, term_loc: GenContext) {
-        let mut classify_info = ClassifyInfo { arg_c: 0, arity: term.arity() };
+    fn try_set_chunk_at_inlined_boundary(&mut self) -> bool {
+        if self.current_chunk_type.is_last() {
+            self.current_chunk_type = ChunkType::Mid;
+            self.current_chunk_num += 1;
+            true
+        } else {
+            false
+        }
+    }
 
-        // second arg is true to iterate the root, which may be a variable
-        for term_ref in breadth_first_iter(term, true) {
-            if let TermRef::Var(lvl, _, var_name) = term_ref {
-                let var_info = VarInfo { var_ptr: VarPtr::from(&var_name), lvl, classify_info };
-                self.probe_body_var(var_name, term_loc, var_info);
-            }
+    fn try_set_chunk_at_call_boundary(&mut self) -> bool {
+        if self.current_chunk_type.is_last() {
+            self.current_chunk_num += 1;
+            true
+        } else {
+            self.current_chunk_type = ChunkType::Last;
+            false
+        }
+    }
 
-            if let Level::Shallow = term_ref.level() {
-                classify_info.arg_c += 1;
+    fn probe_body_term(&mut self, arg_c: usize, arity: usize, term: &Term) {
+        let classify_info = ClassifyInfo { arg_c, arity };
+
+        // second arg is true to iterate the root, which may be a variable
+        for term_ref in breadth_first_iter(term, RootIterationPolicy::Iterated) {
+            if let TermRef::Var(lvl, _, var_ptr) = term_ref {
+                // root terms are shallow here (since we're iterating a
+                // body term) so take the child level.
+                let lvl = lvl.child_level();
+                self.probe_body_var(VarInfo {
+                    var_ptr,
+                    lvl,
+                    classify_info,
+                    chunk_type: self.current_chunk_type,
+                });
             }
         }
     }
 
-    fn probe_body_var(&mut self, var_name: Var, term_loc: GenContext, var_info: VarInfo) {
-        let branch_info_v = self.branch_map.entry(var_name)
+    fn probe_body_var(&mut self, var_info: VarInfo) {
+        let term_loc = self.current_chunk_type.to_gen_context(self.current_chunk_num);
+
+        let branch_info_v = self.branch_map.entry(var_info.var_ptr.clone())
             .or_insert_with(|| vec![]);
 
         let needs_new_branch = if let Some(last_bi) = branch_info_v.last() {
@@ -409,18 +404,17 @@ impl VariableClassifier {
         chunk_info.vars.push(var_info);
     }
 
-    fn probe_in_situ_var(&mut self, chunk_type: ChunkType, var_num: usize) {
-        let classify_info = ClassifyInfo { arg_c: 0, arity: 0 };
+    fn probe_in_situ_var(&mut self, var_num: usize) {
+        let classify_info = ClassifyInfo { arg_c: 1, arity: 1 };
 
         let var_info = VarInfo {
-            var_ptr: VarPtr::InSitu(var_num),
+            var_ptr: VarPtr::from(Var::InSitu(var_num)),
             classify_info,
+            chunk_type: self.current_chunk_type,
             lvl: Level::Shallow,
         };
 
-        let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
-
-        self.probe_body_var(Var::Generated(var_num), term_loc, var_info);
+        self.probe_body_var(var_info);
     }
 
     fn classify_head_variables(&mut self, term: &Term) -> Result<(), CompilationError> {
@@ -430,43 +424,55 @@ impl VariableClassifier {
             _ => return Err(CompilationError::InvalidRuleHead),
         }
 
-        let mut classify_info = ClassifyInfo { arg_c: 0, arity: term.arity() };
-
-        // false argument to breadth_first_iter because the root is not iterable.
-        for term_ref in breadth_first_iter(term, false) {
-            if let TermRef::Var(lvl, _, var_name) = term_ref {
-                // the body of the if let here is an inlined
-                // "probe_head_var". note the difference between it
-                // and "probe_body_var".
-                let branch_info_v = self.branch_map.entry(Var::from(var_name))
-                    .or_insert_with(|| vec![]);
-
-                let needs_new_branch = branch_info_v.is_empty();
+        let mut classify_info = ClassifyInfo { arg_c: 1, arity: term.arity() };
 
-                if needs_new_branch {
-                    branch_info_v.push(BranchInfo::new(self.current_branch_num.clone()));
-                }
+        match term {
+            Term::Clause(_, _, terms) => {
+                for term in terms.into_iter() {
+                    for term_ref in breadth_first_iter(term, RootIterationPolicy::Iterated) {
+                        if let TermRef::Var(lvl, _, var_ptr) = term_ref {
+                            // a body term, so we need the child level here.
+                            let lvl = lvl.child_level();
+
+                            // the body of the if let here is an inlined
+                            // "probe_head_var". note the difference between it
+                            // and "probe_body_var".
+                            let branch_info_v = self.branch_map.entry(var_ptr.clone())
+                                .or_insert_with(|| vec![]);
+
+                            let needs_new_branch = branch_info_v.is_empty();
+
+                            if needs_new_branch {
+                                branch_info_v.push(BranchInfo::new(self.current_branch_num.clone()));
+                            }
 
-                let branch_info = branch_info_v.last_mut().unwrap();
-                let needs_new_chunk = branch_info.chunks.is_empty();
+                            let branch_info = branch_info_v.last_mut().unwrap();
+                            let needs_new_chunk = branch_info.chunks.is_empty();
 
-                if needs_new_chunk {
-                    branch_info.chunks.push(ChunkInfo {
-                        chunk_num: self.current_chunk_num,
-                        term_loc: GenContext::Head,
-                        vars: vec![]
-                    });
-                }
+                            if needs_new_chunk {
+                                branch_info.chunks.push(ChunkInfo {
+                                    chunk_num: self.current_chunk_num,
+                                    term_loc: GenContext::Head,
+                                    vars: vec![],
+                                });
+                            }
 
-                let chunk_info = branch_info.chunks.last_mut().unwrap();
-                let var_info = VarInfo { var_ptr: VarPtr::from(&var_name), classify_info, lvl };
+                            let chunk_info = branch_info.chunks.last_mut().unwrap();
+                            let var_info = VarInfo {
+                                var_ptr,
+                                classify_info,
+                                chunk_type: self.current_chunk_type,
+                                lvl,
+                            };
 
-                chunk_info.vars.push(var_info);
-            }
+                            chunk_info.vars.push(var_info);
+                        }
+                    }
 
-            if let Level::Shallow = term_ref.level() {
-                classify_info.arg_c += 1;
+                    classify_info.arg_c += 1;
+                }
             }
+            _ => {}
         }
 
         Ok(())
@@ -476,10 +482,11 @@ impl VariableClassifier {
         &mut self,
         loader: &mut Loader<'a, LS>,
         term: Term,
-    ) -> Result<Vec<QueryTerm>, CompilationError> {
+    ) -> Result<ChunkedTermVec, CompilationError> {
         let mut state_stack = vec![TraversalState::Term(term)];
-        let mut build_stack = vec![];
-        let mut chunk_type  = ChunkType::Head;
+        let mut build_stack = ChunkedTermVec::new();
+
+        self.current_chunk_type = ChunkType::Mid;
 
         while let Some(traversal_st) = state_stack.pop() {
             match traversal_st {
@@ -495,64 +502,78 @@ impl VariableClassifier {
                     self.root_set.insert(branch_num.clone());
                     self.current_branch_num = branch_num;
                 }
-                TraversalState::IncrChunkNum => {
-                    self.current_chunk_num += 1;
-                    chunk_type = ChunkType::Mid;
-                    build_stack.push(QueryTerm::ChunkTypeBoundary(chunk_type));
-                }
                 TraversalState::ResetCallPolicy(call_policy) => {
                     self.call_policy = call_policy;
                 }
-                TraversalState::SetLastChunkType => {
-                    chunk_type = ChunkType::Last;
-                    build_stack.push(QueryTerm::ChunkTypeBoundary(chunk_type));
-                }
-                TraversalState::BuildDisjunct(reset_chunk_type, preceding_len) => {
-                    chunk_type = reset_chunk_type;
-                    build_stack.push(QueryTerm::ChunkTypeBoundary(chunk_type));
+                TraversalState::BuildDisjunct(preceding_len) => {
                     flatten_into_disjunct(&mut build_stack, preceding_len);
+
+                    // self.current_chunk_type = ChunkType::Last;
+                    self.current_chunk_type = ChunkType::Mid;
+                    self.current_chunk_num += 1;
                 }
                 TraversalState::BuildFinalDisjunct(preceding_len) => {
                     flatten_into_disjunct(&mut build_stack, preceding_len);
+
+                    self.current_chunk_type = ChunkType::Mid;
+                    self.current_chunk_num += 1;
                 }
-                TraversalState::GetCutPoint(var_num) => {
-                    let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
+                TraversalState::GetCutPoint { var_num, prev_b } => {
+                    if self.try_set_chunk_at_inlined_boundary() {
+                        build_stack.add_chunk();
+                    }
 
-                    self.probe_in_situ_var(term_loc, var_num);
-                    build_stack.push(QueryTerm::GetCutPoint(var_num));
+                    self.probe_in_situ_var(var_num);
+                    build_stack.push_chunk_term(QueryTerm::GetCutPoint { var_num, prev_b });
                 }
-                TraversalState::LocalCut(var_num) => {
-                    let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
+                TraversalState::Cut { var_num, is_global } => {
+                    if self.try_set_chunk_at_inlined_boundary() {
+                        build_stack.add_chunk();
+                    }
+
+                    self.probe_in_situ_var(var_num);
 
-                    self.probe_in_situ_var(term_loc, var_num);
-                    build_stack.push(QueryTerm::LocalCut(var_num));
+                    build_stack.push_chunk_term(
+                        if is_global {
+                            QueryTerm::GlobalCut(var_num)
+                        } else {
+                            QueryTerm::LocalCut(var_num)
+                        }
+                    );
                 }
                 TraversalState::Fail => {
-                    build_stack.push(QueryTerm::Fail);
+                    build_stack.push_chunk_term(QueryTerm::Fail);
                 }
                 TraversalState::Term(term) => {
+                    // return true iff new chunk should be added.
+                    let update_chunk_data = |classifier: &mut Self, predicate_name, arity| {
+                        if ClauseType::is_inlined(predicate_name, arity) {
+                            classifier.try_set_chunk_at_inlined_boundary()
+                        } else {
+                            classifier.try_set_chunk_at_call_boundary()
+                        }
+                    };
+
                     match term {
-                        Term::Clause(_, atom!(","), terms) if terms.len() == 2 => {
-                            let iter = unfold_by_str(terms[1], atom!(","))
+                        Term::Clause(_, atom!(","), mut terms) if terms.len() == 2 => {
+                            let tail = terms.pop().unwrap();
+                            let head = terms.pop().unwrap();
+
+                            let iter = unfold_by_str(tail, atom!(","))
                                 .into_iter()
                                 .rev()
-                                .chain(std::iter::once(terms[0]))
+                                .chain(std::iter::once(head))
                                 .map(TraversalState::Term);
 
-                            if ChunkType::Mid != chunk_type {
-                                if insert_set_last_chunk_type(&mut state_stack, iter) {
-                                    if chunk_type.is_last() {
-                                        chunk_type = ChunkType::Mid;
-                                    }
-                                }
-                            } else {
-                                state_stack.extend(iter);
-                            }
+                            state_stack.extend(iter);
                         }
-                        Term::Clause(_, atom!(";"), terms) if terms.len() == 2 => {
+                        Term::Clause(_, atom!(";"), mut terms) if terms.len() == 2 => {
+                            let tail = terms.pop().unwrap();
+                            let head = terms.pop().unwrap();
+
                             let first_branch_num = self.current_branch_num.split();
-                            let branches: Vec<_> = std::iter::once(terms[0])
-                                .chain(unfold_by_str(terms[1], atom!(";")).into_iter())
+                            let branches: Vec<_> = std::iter::once(head)
+                                .chain(unfold_by_str(tail, atom!(";")).into_iter())
                                 .collect();
 
                             let mut branch_numbers = vec![first_branch_num];
@@ -568,7 +589,7 @@ impl VariableClassifier {
                             }
 
                             let build_stack_len = build_stack.len();
-                            build_stack.push(QueryTerm::Branch(Vec::with_capacity(branches.len())));
+                            build_stack.reserve_branch(branches.len());
 
                             state_stack.push(TraversalState::RepBranchNum(
                                 self.current_branch_num.halve_delta(),
@@ -578,47 +599,52 @@ impl VariableClassifier {
                             let final_disjunct_loc = state_stack.len();
 
                             for (term, branch_num) in iter.rev() {
-                                state_stack.push(TraversalState::BuildDisjunct(chunk_type, build_stack_len));
-
+                                state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
                                 state_stack.push(TraversalState::RemoveBranchNum);
                                 state_stack.push(TraversalState::Term(term));
                                 state_stack.push(TraversalState::AddBranchNum(branch_num));
                             }
 
-                            state_stack[final_disjunct_loc] =
-                                TraversalState::BuildFinalDisjunct(build_stack_len);
+                            if let TraversalState::BuildDisjunct(build_stack_len) = state_stack[final_disjunct_loc] {
+                                state_stack[final_disjunct_loc] = TraversalState::BuildFinalDisjunct(build_stack_len);
+                            }
                         }
                         Term::Clause(_, atom!("->"), mut terms) if terms.len() == 2 => {
                             let then_term = terms.pop().unwrap();
                             let if_term = terms.pop().unwrap();
 
-                            let iter = vec![TraversalState::Term(then_term),
-                                            TraversalState::LocalCut(self.var_num),
-                                            TraversalState::Term(if_term),
-                                            TraversalState::GetCutPoint(self.var_num)]
-                                .into_iter();
+                            let prev_b = if matches!(state_stack.last(), Some(TraversalState::RemoveBranchNum)) {
+                                // check if the second-to-last element is a regular BuildDisjunct, as we don't
+                                // want to add GetPrevLevel in case of a TrustMe.
+                                matches!(state_stack.iter().rev().nth(1), Some(TraversalState::BuildDisjunct(..)))
+                            } else {
+                                false
+                            };
 
-                            self.var_num += 1;
+                            state_stack.push(TraversalState::Term(then_term));
+                            state_stack.push(TraversalState::Cut { var_num: self.var_num, is_global: false });
+                            state_stack.push(TraversalState::Term(if_term));
+                            state_stack.push(TraversalState::GetCutPoint { var_num: self.var_num, prev_b });
 
-                            if ChunkType::Mid != chunk_type {
-                                if insert_set_last_chunk_type(&mut state_stack, iter) {
-                                    if chunk_type.is_last() {
-                                        chunk_type = ChunkType::Mid;
-                                    }
-                                }
-                            }
+                            self.var_num += 1;
                         }
-                        Term::Clause(_, atom!("\\+"), terms) if terms.len() == 1 => {
+                        Term::Clause(_, atom!("\\+"), mut terms) if terms.len() == 1 => {
+                            let not_term = terms.pop().unwrap();
+                            let build_stack_len = build_stack.len();
+
+                            build_stack.reserve_branch(2);
+
+                            state_stack.push(TraversalState::BuildFinalDisjunct(build_stack_len));
+                            state_stack.push(TraversalState::Term(Term::Clause(Cell::default(), atom!("$succeed"), vec![])));
+                            state_stack.push(TraversalState::BuildDisjunct(build_stack_len));
                             state_stack.push(TraversalState::Fail);
-                            state_stack.push(TraversalState::LocalCut(self.var_num));
-                            state_stack.push(TraversalState::Term(terms[0]));
-                            state_stack.push(TraversalState::GetCutPoint(self.var_num));
+                            state_stack.push(TraversalState::Cut { var_num: self.var_num, is_global: false });
+                            state_stack.push(TraversalState::Term(not_term));
+                            state_stack.push(TraversalState::GetCutPoint { var_num: self.var_num, prev_b: true });
 
                             self.var_num += 1;
                         }
                         Term::Clause(_, atom!(":"), mut terms) if terms.len() == 2 => {
-                            let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
-
                             let predicate_name = terms.pop().unwrap();
                             let module_name = terms.pop().unwrap();
 
@@ -627,11 +653,11 @@ impl VariableClassifier {
                                     Term::Literal(_, Literal::Atom(module_name)),
                                     Term::Literal(_, Literal::Atom(predicate_name)),
                                 ) => {
-                                    if !ClauseType::is_inbuilt(predicate_name, 0) {
-                                        state_stack.push(TraversalState::IncrChunkNum);
+                                    if update_chunk_data(self, predicate_name, 0) {
+                                        build_stack.add_chunk();
                                     }
 
-                                    build_stack.push(
+                                    build_stack.push_chunk_term(
                                         qualified_clause_to_query_term(
                                             loader,
                                             module_name,
@@ -645,15 +671,15 @@ impl VariableClassifier {
                                     Term::Literal(_, Literal::Atom(module_name)),
                                     Term::Clause(_, name, terms),
                                 ) => {
-                                    if !ClauseType::is_inbuilt(name, terms.len()) {
-                                        state_stack.push(TraversalState::IncrChunkNum);
+                                    if update_chunk_data(self, name, terms.len()) {
+                                        build_stack.add_chunk();
                                     }
 
-                                    for term in terms.iter() {
-                                        self.probe_body_term(term, term_loc);
+                                    for (arg_c, term) in terms.iter().enumerate() {
+                                        self.probe_body_term(arg_c + 1, terms.len(), term);
                                     }
 
-                                    build_stack.push(
+                                    build_stack.push_chunk_term(
                                         qualified_clause_to_query_term(
                                             loader,
                                             module_name,
@@ -664,15 +690,17 @@ impl VariableClassifier {
                                     );
                                 }
                                 (module_name, predicate_name) => {
-                                    state_stack.push(TraversalState::IncrChunkNum);
+                                    if update_chunk_data(self, atom!("call"), 2) {
+                                        build_stack.add_chunk();
+                                    }
 
-                                    self.probe_body_term(&module_name, term_loc);
-                                    self.probe_body_term(&predicate_name, term_loc);
+                                    self.probe_body_term(1, 0, &module_name);
+                                    self.probe_body_term(2, 0, &predicate_name);
 
                                     terms.push(module_name);
                                     terms.push(predicate_name);
 
-                                    build_stack.push(
+                                    build_stack.push_chunk_term(
                                         clause_to_query_term(
                                             loader,
                                             atom!("call"),
@@ -683,30 +711,22 @@ impl VariableClassifier {
                                 }
                             }
                         }
-                        Term::Clause(cell, atom!("$call_with_inference_counting"), terms) if terms.len() == 1 => {
-                            let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
-
-                            for term in terms.iter() {
-                                self.probe_body_term(term, term_loc);
-                            }
-
+                        Term::Clause(_, atom!("$call_with_inference_counting"), mut terms) if terms.len() == 1 => {
                             state_stack.push(TraversalState::ResetCallPolicy(self.call_policy));
-                            state_stack.push(TraversalState::Term(terms[0]));
+                            state_stack.push(TraversalState::Term(terms.pop().unwrap()));
 
                             self.call_policy = CallPolicy::Counted;
                         }
-                        Term::Clause(cell, name, terms) => {
-                            if !ClauseType::is_inbuilt(name, terms.len()) {
-                                state_stack.push(TraversalState::IncrChunkNum);
+                        Term::Clause(_, name, terms) => {
+                            if update_chunk_data(self, name, terms.len()) {
+                                build_stack.add_chunk();
                             }
 
-                            let term_loc = chunk_type.to_gen_context(self.current_chunk_num);
-
-                            for term in terms.iter() {
-                                self.probe_body_term(term, term_loc);
+                            for (arg_c, term) in terms.iter().enumerate() {
+                                self.probe_body_term(arg_c + 1, terms.len(), term);
                             }
 
-                            build_stack.push(
+                            build_stack.push_chunk_term(
                                 clause_to_query_term(
                                     loader,
                                     name,
@@ -716,14 +736,24 @@ impl VariableClassifier {
                             );
                         }
                         Term::Literal(_, Literal::Atom(atom!("!")) | Literal::Char('!')) => {
-                            build_stack.push(QueryTerm::GlobalCut);
+                            if self.global_cut_var_num.is_none() {
+                                self.global_cut_var_num = Some(self.var_num);
+                                self.var_num += 1;
+                            }
+
+                            self.probe_in_situ_var(self.global_cut_var_num.unwrap());
+
+                            state_stack.push(TraversalState::Cut {
+                                var_num: self.global_cut_var_num.unwrap(),
+                                is_global: true,
+                            });
                         }
-                        Term::Literal(cell, Literal::Atom(name)) => {
-                            if !ClauseType::is_inbuilt(name, 0) {
-                                state_stack.push(TraversalState::IncrChunkNum);
+                        Term::Literal(_, Literal::Atom(name)) => {
+                            if update_chunk_data(self, name, 0) {
+                                build_stack.add_chunk();
                             }
 
-                            build_stack.push(
+                            build_stack.push_chunk_term(
                                 clause_to_query_term(
                                     loader,
                                     name,
@@ -732,7 +762,6 @@ impl VariableClassifier {
                                 ),
                             );
                         }
-
                         _ => {
                             return Err(CompilationError::InadmissibleQueryTerm);
                         }
@@ -746,61 +775,76 @@ impl VariableClassifier {
 }
 
 impl BranchMap {
-    pub fn separate_and_classify_variables(&mut self, mut var_num: usize) -> VarData {
+    pub fn separate_and_classify_variables(
+        &mut self,
+        var_num: usize,
+        global_cut_var_num: Option<usize>,
+        current_chunk_num: usize,
+    ) -> VarData {
         let mut var_data = VarData {
-            records:  vec![VarRecord::default(); self.len()],
-            fixtures: VariableFixtures::new(),
+            records: VariableRecords::new(var_num),
+            global_cut_var_num,
+            allocates: current_chunk_num > 0,
         };
 
         for (var, branches) in self.iter_mut() {
-            for branch in branches.iter_mut() {
-                let mut num_occurrences = 0;
-
-                let idx = if let Var::Generated(var_num) = var {
-                    *var_num
+            let (mut var_num, var_num_incr) =
+                if let Var::InSitu(var_num) = *var.borrow() {
+                    (var_num, false)
                 } else {
-                    var_num += 1;
-                    var_num - 1
+                    (var_data.records.len(), true)
                 };
 
-                var_data.records[idx].classification =
-                    if branch.chunks.len() > 1 {
-                        VarClassification::Perm
-                    } else {
-                        branch.chunks
-                            .first()
-                            .map(|chunk| if chunk.vars.len() > 1 {
-                                VarClassification::Temp
-                            } else {
-                                VarClassification::Void
-                            })
-                            .unwrap_or(VarClassification::Void)
-                    };
+            for branch in branches.iter_mut() {
+                if var_num_incr {
+                    var_num = var_data.records.len();
+                    var_data.records.push(VariableRecord::default());
+                }
 
-                var_data.records[idx].chunk_occurrences.reserve(branch.chunks.len());
+                if branch.chunks.len() <= 1 { // true iff var is a temporary variable.
+                    debug_assert_eq!(branch.chunks.len(), 1);
 
-                for chunk in branch.chunks.iter_mut() {
-                    var_data.records[idx].num_occurrences += chunk.vars.len();
+                    let chunk = &mut branch.chunks[0];
+                    let mut temp_var_data = TempVarData::new();
 
-                    if let VarClassification::Temp = classification {
-                        for var_info in chunk.vars.iter_mut() {
-                            var_info.var_ptr.set(Var::Generated(var_num));
-                            var_data.fixtures.mark_temp_var(&var_info);
-                        }
-                    } else {
-                        for var_info in chunk.vars.iter_mut() {
-                            var_info.var_ptr.set(Var::Generated(var_num));
+                    for var_info in chunk.vars.iter_mut() {
+                        if var_info.lvl == Level::Shallow {
+                            let term_loc = var_info.chunk_type.to_gen_context(chunk.chunk_num);
+                            temp_var_data.use_set.insert((term_loc, var_info.classify_info.arg_c));
                         }
                     }
 
-                    var_data.records[idx].chunk_occurrences.push(chunk.chunk_num);
+                    var_data.records[var_num].allocation = VarAlloc::Temp {
+                        term_loc: chunk.term_loc,
+                        temp_reg: 0,
+                        temp_var_data,
+                        safety: VarSafetyStatus::Needed,
+                        to_perm_var_num: None,
+                    };
+                } // else VarAlloc is already a Perm variant, as it's the default.
+
+                for chunk in branch.chunks.iter_mut() {
+                    var_data.records[var_num].num_occurrences += chunk.vars.len();
+
+                    for var_info in chunk.vars.iter_mut() {
+                        var_info.var_ptr.set(Var::Generated(var_num));
+                    }
                 }
             }
         }
 
-        debug_assert_eq!(var_data.records.len(), var_num);
+        // debug_assert_eq!(var_data.records.len(), var_num);
 
-        var_data.fixtures.populate_restricting_sets();
+        var_data.records.populate_restricting_sets();
         var_data
     }
 }
+
+#[cfg(test)]
+mod tests {
+    #[test]
+    fn disjunct_compilation() {
+        let mut wam = MachineState::new();
+        let mut op_dir = default_op_dir();
+    }
+}
index 92eca80fa29bec58446ba9bbb1b0146645f3037d..1d310bcd7afc75027859f587aff08675fc098053 100644 (file)
@@ -1152,6 +1152,16 @@ impl Machine {
                     self.machine_st[r] = fixnum_as_cell!(Fixnum::build_with(b0 as i64));
                     self.machine_st.p += 1;
                 }
+                &Instruction::GetPrevLevel(r) => {
+                    let prev_b = self.machine_st.stack.index_or_frame(self.machine_st.b).prelude.b;
+
+                    self.machine_st[r] = fixnum_as_cell!(Fixnum::build_with(prev_b as i64));
+                    self.machine_st.p += 1;
+                }
+                &Instruction::GetCutPoint(r) => {
+                    self.machine_st[r] = fixnum_as_cell!(Fixnum::build_with(self.machine_st.b as i64));
+                    self.machine_st.p += 1;
+                }
                 &Instruction::Cut(r) => {
                     let value = self.machine_st[r];
                     self.machine_st.cut_body(value);
@@ -1170,7 +1180,7 @@ impl Machine {
                 &Instruction::Allocate(num_cells) => {
                     self.machine_st.allocate(num_cells);
                 }
-                &Instruction::DefaultCallAcyclicTerm(_) => {
+                &Instruction::DefaultCallAcyclicTerm => {
                     let addr = self.machine_st.registers[1];
 
                     if self.machine_st.is_cyclic_term(addr) {
@@ -1179,7 +1189,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::DefaultExecuteAcyclicTerm(_) => {
+                &Instruction::DefaultExecuteAcyclicTerm => {
                     let addr = self.machine_st.registers[1];
 
                     if self.machine_st.is_cyclic_term(addr) {
@@ -1188,23 +1198,23 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::DefaultCallArg(_) => {
+                &Instruction::DefaultCallArg => {
                     try_or_throw!(self.machine_st, self.machine_st.try_arg());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::DefaultExecuteArg(_) => {
+                &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(_) => {
+                &Instruction::DefaultCallCompare => {
                     try_or_throw!(self.machine_st, self.machine_st.compare());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::DefaultExecuteCompare(_) => {
+                &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(_) => {
+                &Instruction::DefaultCallTermGreaterThan => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1214,7 +1224,7 @@ impl Machine {
                         self.machine_st.backtrack();
                     }
                 }
-                &Instruction::DefaultExecuteTermGreaterThan(_) => {
+                &Instruction::DefaultExecuteTermGreaterThan => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1224,7 +1234,7 @@ impl Machine {
                         self.machine_st.backtrack();
                     }
                 }
-                &Instruction::DefaultCallTermLessThan(_) => {
+                &Instruction::DefaultCallTermLessThan => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1234,7 +1244,7 @@ impl Machine {
                         self.machine_st.backtrack();
                     }
                 }
-                &Instruction::DefaultExecuteTermLessThan(_) => {
+                &Instruction::DefaultExecuteTermLessThan => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1244,7 +1254,7 @@ impl Machine {
                         self.machine_st.backtrack();
                     }
                 }
-                &Instruction::DefaultCallTermGreaterThanOrEqual(_) => {
+                &Instruction::DefaultCallTermGreaterThanOrEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1257,7 +1267,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultExecuteTermGreaterThanOrEqual(_) => {
+                &Instruction::DefaultExecuteTermGreaterThanOrEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1270,7 +1280,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultCallTermLessThanOrEqual(_) => {
+                &Instruction::DefaultCallTermLessThanOrEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1283,7 +1293,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultExecuteTermLessThanOrEqual(_) => {
+                &Instruction::DefaultExecuteTermLessThanOrEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1296,11 +1306,11 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultCallRead(_) => {
+                &Instruction::DefaultCallRead => {
                     try_or_throw!(self.machine_st, self.read());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::DefaultExecuteRead(_) => {
+                &Instruction::DefaultExecuteRead => {
                     try_or_throw!(self.machine_st, self.read());
 
                     if self.machine_st.fail {
@@ -1309,11 +1319,11 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::DefaultCallCopyTerm(_) => {
+                &Instruction::DefaultCallCopyTerm => {
                     self.machine_st.copy_term(AttrVarPolicy::DeepCopy);
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::DefaultExecuteCopyTerm(_) => {
+                &Instruction::DefaultExecuteCopyTerm => {
                     self.machine_st.copy_term(AttrVarPolicy::DeepCopy);
 
                     if self.machine_st.fail {
@@ -1322,7 +1332,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::DefaultCallTermEqual(_) => {
+                &Instruction::DefaultCallTermEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1332,7 +1342,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::DefaultExecuteTermEqual(_) => {
+                &Instruction::DefaultExecuteTermEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1342,26 +1352,26 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::DefaultCallGround(_) => {
+                &Instruction::DefaultCallGround => {
                     if self.machine_st.ground_test() {
                         self.machine_st.backtrack();
                     } else {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::DefaultExecuteGround(_) => {
+                &Instruction::DefaultExecuteGround => {
                     if self.machine_st.ground_test() {
                         self.machine_st.backtrack();
                     } else {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::DefaultCallFunctor(_) => {
+                &Instruction::DefaultCallFunctor => {
                     try_or_throw!(self.machine_st, self.machine_st.try_functor());
 
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::DefaultExecuteFunctor(_) => {
+                &Instruction::DefaultExecuteFunctor => {
                     try_or_throw!(self.machine_st, self.machine_st.try_functor());
 
                     if self.machine_st.fail {
@@ -1370,7 +1380,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::DefaultCallTermNotEqual(_) => {
+                &Instruction::DefaultCallTermNotEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1380,7 +1390,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::DefaultExecuteTermNotEqual(_) => {
+                &Instruction::DefaultExecuteTermNotEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1390,19 +1400,19 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::DefaultCallSort(_) => {
+                &Instruction::DefaultCallSort => {
                     try_or_throw!(self.machine_st, self.machine_st.sort());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::DefaultExecuteSort(_) => {
+                &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(_) => {
+                &Instruction::DefaultCallKeySort => {
                     try_or_throw!(self.machine_st, self.machine_st.keysort());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::DefaultExecuteKeySort(_) => {
+                &Instruction::DefaultExecuteKeySort => {
                     try_or_throw!(self.machine_st, self.machine_st.keysort());
 
                     if self.machine_st.fail {
@@ -1411,15 +1421,15 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::DefaultCallIs(r, at, _) => {
+                &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, _) => {
+                &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(_) => {
+                &Instruction::CallAcyclicTerm => {
                     let addr = self.machine_st.registers[1];
 
                     if self.machine_st.is_cyclic_term(addr) {
@@ -1433,7 +1443,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteAcyclicTerm(_) => {
+                &Instruction::ExecuteAcyclicTerm => {
                     let addr = self.machine_st.registers[1];
 
                     if self.machine_st.is_cyclic_term(addr) {
@@ -1447,7 +1457,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallArg(_) => {
+                &Instruction::CallArg => {
                     try_or_throw!(self.machine_st, self.machine_st.try_arg());
 
                     if self.machine_st.fail {
@@ -1461,7 +1471,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteArg(_) => {
+                &Instruction::ExecuteArg => {
                     try_or_throw!(self.machine_st, self.machine_st.try_arg());
 
                     if self.machine_st.fail {
@@ -1475,7 +1485,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallCompare(_) => {
+                &Instruction::CallCompare => {
                     try_or_throw!(self.machine_st, self.machine_st.compare());
 
                     if self.machine_st.fail {
@@ -1489,7 +1499,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteCompare(_) => {
+                &Instruction::ExecuteCompare => {
                     try_or_throw!(self.machine_st, self.machine_st.compare());
 
                     if self.machine_st.fail {
@@ -1503,7 +1513,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallTermGreaterThan(_) => {
+                &Instruction::CallTermGreaterThan => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1518,7 +1528,7 @@ impl Machine {
                         self.machine_st.backtrack();
                     }
                 }
-                &Instruction::ExecuteTermGreaterThan(_) => {
+                &Instruction::ExecuteTermGreaterThan => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1533,7 +1543,7 @@ impl Machine {
                         self.machine_st.backtrack();
                     }
                 }
-                &Instruction::CallTermLessThan(_) => {
+                &Instruction::CallTermLessThan => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1548,7 +1558,7 @@ impl Machine {
                         self.machine_st.backtrack();
                     }
                 }
-                &Instruction::ExecuteTermLessThan(_) => {
+                &Instruction::ExecuteTermLessThan => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1563,7 +1573,7 @@ impl Machine {
                         self.machine_st.backtrack();
                     }
                 }
-                &Instruction::CallTermGreaterThanOrEqual(_) => {
+                &Instruction::CallTermGreaterThanOrEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1581,7 +1591,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::ExecuteTermGreaterThanOrEqual(_) => {
+                &Instruction::ExecuteTermGreaterThanOrEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1599,7 +1609,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::CallTermLessThanOrEqual(_) => {
+                &Instruction::CallTermLessThanOrEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1617,7 +1627,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::ExecuteTermLessThanOrEqual(_) => {
+                &Instruction::ExecuteTermLessThanOrEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1635,7 +1645,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::CallRead(_) => {
+                &Instruction::CallRead => {
                     try_or_throw!(self.machine_st, self.read());
 
                     if self.machine_st.fail {
@@ -1649,7 +1659,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteRead(_) => {
+                &Instruction::ExecuteRead => {
                     try_or_throw!(self.machine_st, self.read());
 
                     if self.machine_st.fail {
@@ -1663,7 +1673,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallCopyTerm(_) => {
+                &Instruction::CallCopyTerm => {
                     self.machine_st.copy_term(AttrVarPolicy::DeepCopy);
 
                     if self.machine_st.fail {
@@ -1677,7 +1687,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteCopyTerm(_) => {
+                &Instruction::ExecuteCopyTerm => {
                     self.machine_st.copy_term(AttrVarPolicy::DeepCopy);
 
                     if self.machine_st.fail {
@@ -1691,7 +1701,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallTermEqual(_) => {
+                &Instruction::CallTermEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1706,7 +1716,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteTermEqual(_) => {
+                &Instruction::ExecuteTermEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1721,7 +1731,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallGround(_) => {
+                &Instruction::CallGround => {
                     if self.machine_st.ground_test() {
                         self.machine_st.backtrack();
                     } else {
@@ -1733,7 +1743,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteGround(_) => {
+                &Instruction::ExecuteGround => {
                     if self.machine_st.ground_test() {
                         self.machine_st.backtrack();
                     } else {
@@ -1745,7 +1755,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallFunctor(_) => {
+                &Instruction::CallFunctor => {
                     try_or_throw!(self.machine_st, self.machine_st.try_functor());
 
                     if self.machine_st.fail {
@@ -1759,7 +1769,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteFunctor(_) => {
+                &Instruction::ExecuteFunctor => {
                     try_or_throw!(self.machine_st, self.machine_st.try_functor());
 
                     if self.machine_st.fail {
@@ -1773,7 +1783,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallTermNotEqual(_) => {
+                &Instruction::CallTermNotEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1788,7 +1798,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteTermNotEqual(_) => {
+                &Instruction::ExecuteTermNotEqual => {
                     let a1 = self.machine_st.registers[1];
                     let a2 = self.machine_st.registers[2];
 
@@ -1803,7 +1813,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallSort(_) => {
+                &Instruction::CallSort => {
                     try_or_throw!(self.machine_st, self.machine_st.sort());
 
                     if self.machine_st.fail {
@@ -1817,7 +1827,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteSort(_) => {
+                &Instruction::ExecuteSort => {
                     try_or_throw!(self.machine_st, self.machine_st.sort());
 
                     if self.machine_st.fail {
@@ -1831,7 +1841,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallKeySort(_) => {
+                &Instruction::CallKeySort => {
                     try_or_throw!(self.machine_st, self.machine_st.keysort());
 
                     if self.machine_st.fail {
@@ -1845,7 +1855,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteKeySort(_) => {
+                &Instruction::ExecuteKeySort => {
                     try_or_throw!(self.machine_st, self.machine_st.keysort());
 
                     if self.machine_st.fail {
@@ -1859,7 +1869,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallIs(r, at, _) => {
+                &Instruction::CallIs(r, at) => {
                     try_or_throw!(self.machine_st, self.machine_st.is(r, at));
 
                     if self.machine_st.fail {
@@ -1873,7 +1883,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteIs(r, at, _) => {
+                &Instruction::ExecuteIs(r, at) => {
                     try_or_throw!(self.machine_st, self.machine_st.is(r, at));
 
                     if self.machine_st.fail {
@@ -1887,7 +1897,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallN(arity, _) => {
+                &Instruction::CallN(arity) => {
                     let pred = self.machine_st.registers[1];
 
                     for i in 2..arity + 1 {
@@ -1910,7 +1920,7 @@ impl Machine {
                         );
                     }
                 }
-                &Instruction::ExecuteN(arity, _) => {
+                &Instruction::ExecuteN(arity) => {
                     let pred = self.machine_st.registers[1];
 
                     for i in 2..arity + 1 {
@@ -1933,7 +1943,7 @@ impl Machine {
                         );
                     }
                 }
-                &Instruction::DefaultCallN(arity, _) => {
+                &Instruction::DefaultCallN(arity) => {
                     let pred = self.machine_st.registers[1];
 
                     for i in 2..arity + 1 {
@@ -1951,7 +1961,7 @@ impl Machine {
                         self.machine_st.backtrack();
                     }
                 }
-                &Instruction::DefaultExecuteN(arity, _) => {
+                &Instruction::DefaultExecuteN(arity) => {
                     let pred = self.machine_st.registers[1];
 
                     for i in 2..arity + 1 {
@@ -1969,7 +1979,7 @@ impl Machine {
                         self.machine_st.backtrack();
                     }
                 }
-                &Instruction::CallNumberLessThanOrEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -1987,7 +1997,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::ExecuteNumberLessThanOrEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2005,7 +2015,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::CallNumberEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2023,7 +2033,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::ExecuteNumberEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2041,7 +2051,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::CallNumberNotEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2059,7 +2069,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::ExecuteNumberNotEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2077,7 +2087,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::CallNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2095,7 +2105,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::ExecuteNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2113,7 +2123,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::CallNumberGreaterThan(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2131,7 +2141,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::ExecuteNumberGreaterThan(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2149,7 +2159,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::CallNumberLessThan(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2167,7 +2177,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::ExecuteNumberLessThan(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2185,7 +2195,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultCallNumberLessThanOrEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2198,7 +2208,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultExecuteNumberLessThanOrEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2211,7 +2221,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultCallNumberNotEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2224,7 +2234,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultExecuteNumberNotEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2237,7 +2247,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultCallNumberEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2250,7 +2260,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultExecuteNumberEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2263,7 +2273,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultCallNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2276,7 +2286,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultExecuteNumberGreaterThanOrEqual(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2289,7 +2299,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultCallNumberGreaterThan(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2302,7 +2312,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultExecuteNumberGreaterThan(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2315,7 +2325,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultCallNumberLessThan(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2328,7 +2338,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::DefaultExecuteNumberLessThan(ref at_1, ref at_2, _) => {
+                &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));
 
@@ -2342,7 +2352,7 @@ impl Machine {
                     }
                 }
                 //
-                &Instruction::CallIsAtom(r, _) => {
+                &Instruction::CallIsAtom(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     read_heap_cell!(d,
@@ -2371,7 +2381,7 @@ impl Machine {
                         }
                     );
                 }
-                &Instruction::ExecuteIsAtom(r, _) => {
+                &Instruction::ExecuteIsAtom(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     read_heap_cell!(d,
@@ -2400,7 +2410,7 @@ impl Machine {
                         }
                     );
                 }
-                &Instruction::CallIsAtomic(r, _) => {
+                &Instruction::CallIsAtomic(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     read_heap_cell!(d,
@@ -2430,7 +2440,7 @@ impl Machine {
                         }
                     );
                 }
-                &Instruction::ExecuteIsAtomic(r, _) => {
+                &Instruction::ExecuteIsAtomic(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     read_heap_cell!(d,
@@ -2460,7 +2470,7 @@ impl Machine {
                         }
                     );
                 }
-                &Instruction::CallIsCompound(r, _) => {
+                &Instruction::CallIsCompound(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     read_heap_cell!(d,
@@ -2491,7 +2501,7 @@ impl Machine {
                         }
                     );
                 }
-                &Instruction::ExecuteIsCompound(r, _) => {
+                &Instruction::ExecuteIsCompound(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     read_heap_cell!(d,
@@ -2522,7 +2532,7 @@ impl Machine {
                         }
                     );
                 }
-                &Instruction::CallIsInteger(r, _) => {
+                &Instruction::CallIsInteger(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     match Number::try_from(d) {
@@ -2541,7 +2551,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::ExecuteIsInteger(r, _) => {
+                &Instruction::ExecuteIsInteger(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     match Number::try_from(d) {
@@ -2560,7 +2570,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::CallIsNumber(r, _) => {
+                &Instruction::CallIsNumber(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     match Number::try_from(d) {
@@ -2572,7 +2582,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::ExecuteIsNumber(r, _) => {
+                &Instruction::ExecuteIsNumber(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     match Number::try_from(d) {
@@ -2584,7 +2594,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::CallIsRational(r, _) => {
+                &Instruction::CallIsRational(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     read_heap_cell!(d,
@@ -2603,7 +2613,7 @@ impl Machine {
                         }
                     );
                 }
-                &Instruction::ExecuteIsRational(r, _) => {
+                &Instruction::ExecuteIsRational(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     read_heap_cell!(d,
@@ -2622,7 +2632,7 @@ impl Machine {
                         }
                     );
                 }
-                &Instruction::CallIsFloat(r, _) => {
+                &Instruction::CallIsFloat(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     match Number::try_from(d) {
@@ -2634,7 +2644,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::ExecuteIsFloat(r, _) => {
+                &Instruction::ExecuteIsFloat(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     match Number::try_from(d) {
@@ -2646,7 +2656,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::CallIsNonVar(r, _) => {
+                &Instruction::CallIsNonVar(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     match d.get_tag() {
@@ -2660,7 +2670,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::ExecuteIsNonVar(r, _) => {
+                &Instruction::ExecuteIsNonVar(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     match d.get_tag() {
@@ -2674,7 +2684,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::CallIsVar(r, _) => {
+                &Instruction::CallIsVar(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     match d.get_tag() {
@@ -2688,7 +2698,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::ExecuteIsVar(r, _) => {
+                &Instruction::ExecuteIsVar(r) => {
                     let d = self.machine_st.store(self.machine_st.deref(self.machine_st[r]));
 
                     match d.get_tag() {
@@ -2702,7 +2712,7 @@ impl Machine {
                         }
                     }
                 }
-                &Instruction::CallNamed(arity, name, ref idx, _) => {
+                &Instruction::CallNamed(arity, name, ref idx) => {
                     let idx = idx.get();
 
                     try_or_throw!(
@@ -2719,7 +2729,7 @@ impl Machine {
                         );
                     }
                 }
-                &Instruction::ExecuteNamed(arity, name, ref idx, _) => {
+                &Instruction::ExecuteNamed(arity, name, ref idx) => {
                     let idx = idx.get();
 
                     try_or_throw!(
@@ -2736,7 +2746,7 @@ impl Machine {
                         );
                     }
                 }
-                &Instruction::DefaultCallNamed(arity, name, ref idx, _) => {
+                &Instruction::DefaultCallNamed(arity, name, ref idx) => {
                     let idx = idx.get();
 
                     try_or_throw!(
@@ -2748,7 +2758,7 @@ impl Machine {
                         self.machine_st.backtrack();
                     }
                 }
-                &Instruction::DefaultExecuteNamed(arity, name, ref idx, _) => {
+                &Instruction::DefaultExecuteNamed(arity, name, ref idx) => {
                     let idx = idx.get();
 
                     try_or_throw!(
@@ -2763,15 +2773,7 @@ impl Machine {
                 &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;
+                &Instruction::JmpByCall(offset) => {
                     self.machine_st.p += offset;
                 }
                 &Instruction::RevJmpBy(offset) => {
@@ -3219,8 +3221,8 @@ impl Machine {
 
                     self.machine_st.p += 1;
                 }
-                &Instruction::PutUnsafeValue(n, arg) => {
-                    let s = stack_loc!(AndFrame, self.machine_st.e, n);
+                &Instruction::PutUnsafeValue(perm_slot, arg) => {
+                    let s = stack_loc!(AndFrame, self.machine_st.e, perm_slot);
                     let addr = self.machine_st.store(self.machine_st.deref(stack_loc_as_cell!(s)));
 
                     if addr.is_protected(self.machine_st.e) {
@@ -3298,11 +3300,11 @@ impl Machine {
                     self.machine_st.p += 1;
                 }
                 //
-                &Instruction::CallAtomChars(_) => {
+                &Instruction::CallAtomChars => {
                     self.atom_chars();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteAtomChars(_) => {
+                &Instruction::ExecuteAtomChars => {
                     self.atom_chars();
 
                     if self.machine_st.fail {
@@ -3311,7 +3313,7 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallAtomCodes(_) => {
+                &Instruction::CallAtomCodes => {
                     try_or_throw!(self.machine_st, self.atom_codes());
 
                     if self.machine_st.fail {
@@ -3320,7 +3322,7 @@ impl Machine {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteAtomCodes(_) => {
+                &Instruction::ExecuteAtomCodes => {
                     try_or_throw!(self.machine_st, self.atom_codes());
 
                     if self.machine_st.fail {
@@ -3329,237 +3331,237 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallAtomLength(_) => {
+                &Instruction::CallAtomLength => {
                     self.atom_length();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteAtomLength(_) => {
+                &Instruction::ExecuteAtomLength => {
                     self.atom_length();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallBindFromRegister(_) => {
+                &Instruction::CallBindFromRegister => {
                     self.bind_from_register();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteBindFromRegister(_) => {
+                &Instruction::ExecuteBindFromRegister => {
                     self.bind_from_register();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallContinuation(_) => {
+                &Instruction::CallContinuation => {
                     try_or_throw!(self.machine_st, self.call_continuation(false));
                 }
-                &Instruction::ExecuteContinuation(_) => {
+                &Instruction::ExecuteContinuation => {
                     try_or_throw!(self.machine_st, self.call_continuation(true));
                 }
-                &Instruction::CallCharCode(_) => {
+                &Instruction::CallCharCode => {
                     try_or_throw!(self.machine_st, self.char_code());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCharCode(_) => {
+                &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(_) => {
+                &Instruction::CallCharType => {
                     self.char_type();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCharType(_) => {
+                &Instruction::ExecuteCharType => {
                     self.char_type();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCharsToNumber(_) => {
+                &Instruction::CallCharsToNumber => {
                     try_or_throw!(self.machine_st, self.chars_to_number());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCharsToNumber(_) => {
+                &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(_) => {
+                &Instruction::CallCodesToNumber => {
                     try_or_throw!(self.machine_st, self.codes_to_number());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCodesToNumber(_) => {
+                &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(_) => {
+                &Instruction::CallCopyTermWithoutAttrVars => {
                     self.copy_term_without_attr_vars();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCopyTermWithoutAttrVars(_) => {
+                &Instruction::ExecuteCopyTermWithoutAttrVars => {
                     self.copy_term_without_attr_vars();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCheckCutPoint(_) => {
+                &Instruction::CallCheckCutPoint => {
                     self.check_cut_point();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCheckCutPoint(_) => {
+                &Instruction::ExecuteCheckCutPoint => {
                     self.check_cut_point();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallClose(_) => {
+                &Instruction::CallClose => {
                     try_or_throw!(self.machine_st, self.close());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteClose(_) => {
+                &Instruction::ExecuteClose => {
                     try_or_throw!(self.machine_st, self.close());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallCopyToLiftedHeap(_) => {
+                &Instruction::CallCopyToLiftedHeap => {
                     self.copy_to_lifted_heap();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteCopyToLiftedHeap(_) => {
+                &Instruction::ExecuteCopyToLiftedHeap => {
                     self.copy_to_lifted_heap();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallCreatePartialString(_) => {
+                &Instruction::CallCreatePartialString => {
                     self.create_partial_string();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCreatePartialString(_) => {
+                &Instruction::ExecuteCreatePartialString => {
                     self.create_partial_string();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCurrentHostname(_) => {
+                &Instruction::CallCurrentHostname => {
                     self.current_hostname();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCurrentHostname(_) => {
+                &Instruction::ExecuteCurrentHostname => {
                     self.current_hostname();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCurrentInput(_) => {
+                &Instruction::CallCurrentInput => {
                     try_or_throw!(self.machine_st, self.current_input());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCurrentInput(_) => {
+                &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(_) => {
+                &Instruction::CallCurrentOutput => {
                     try_or_throw!(self.machine_st, self.current_output());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCurrentOutput(_) => {
+                &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(_) => {
+                &Instruction::CallDirectoryFiles => {
                     try_or_throw!(self.machine_st, self.directory_files());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteDirectoryFiles(_) => {
+                &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(_) => {
+                &Instruction::CallFileSize => {
                     self.file_size();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteFileSize(_) => {
+                &Instruction::ExecuteFileSize => {
                     self.file_size();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallFileExists(_) => {
+                &Instruction::CallFileExists => {
                     self.file_exists();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteFileExists(_) => {
+                &Instruction::ExecuteFileExists => {
                     self.file_exists();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallDirectoryExists(_) => {
+                &Instruction::CallDirectoryExists => {
                     self.directory_exists();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteDirectoryExists(_) => {
+                &Instruction::ExecuteDirectoryExists => {
                     self.directory_exists();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallDirectorySeparator(_) => {
+                &Instruction::CallDirectorySeparator => {
                     self.directory_separator();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteDirectorySeparator(_) => {
+                &Instruction::ExecuteDirectorySeparator => {
                     self.directory_separator();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallMakeDirectory(_) => {
+                &Instruction::CallMakeDirectory => {
                     self.make_directory();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteMakeDirectory(_) => {
+                &Instruction::ExecuteMakeDirectory => {
                     self.make_directory();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallMakeDirectoryPath(_) => {
+                &Instruction::CallMakeDirectoryPath => {
                     self.make_directory_path();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteMakeDirectoryPath(_) => {
+                &Instruction::ExecuteMakeDirectoryPath => {
                     self.make_directory_path();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallDeleteFile(_) => {
+                &Instruction::CallDeleteFile => {
                     self.delete_file();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteDeleteFile(_) => {
+                &Instruction::ExecuteDeleteFile => {
                     self.delete_file();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallRenameFile(_) => {
+                &Instruction::CallRenameFile => {
                     self.rename_file();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteRenameFile(_) => {
+                &Instruction::ExecuteRenameFile => {
                     self.rename_file();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-               &Instruction::CallFileCopy(_) => {
+               &Instruction::CallFileCopy => {
                    self.file_copy();
                    step_or_fail!(self, self.machine_st.p += 1);
                }
-               &Instruction::ExecuteFileCopy(_) => {
+               &Instruction::ExecuteFileCopy => {
                    self.file_copy();
                    step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                }
-                &Instruction::CallWorkingDirectory(_) => {
+                &Instruction::CallWorkingDirectory => {
                     try_or_throw!(self.machine_st, self.working_directory());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteWorkingDirectory(_) => {
+                &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(_) => {
+                &Instruction::CallDeleteDirectory => {
                     self.delete_directory();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteDeleteDirectory(_) => {
+                &Instruction::ExecuteDeleteDirectory => {
                     self.delete_directory();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallPathCanonical(_) => {
+                &Instruction::CallPathCanonical => {
                     try_or_throw!(self.machine_st, self.path_canonical());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePathCanonical(_) => {
+                &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(_) => {
+                &Instruction::CallFileTime => {
                     self.file_time();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteFileTime(_) => {
+                &Instruction::ExecuteFileTime => {
                     self.file_time();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallDynamicModuleResolution(arity, _) => {
+                &Instruction::CallDynamicModuleResolution(arity) => {
                     let (module_name, key) = try_or_throw!(
                         self.machine_st,
                         self.dynamic_module_resolution(arity - 2)
@@ -3574,7 +3576,7 @@ impl Machine {
                         self.machine_st.backtrack();
                     }
                 }
-                &Instruction::ExecuteDynamicModuleResolution(arity, _) => {
+                &Instruction::ExecuteDynamicModuleResolution(arity) => {
                     let (module_name, key) = try_or_throw!(
                         self.machine_st,
                         self.dynamic_module_resolution(arity - 2)
@@ -3589,428 +3591,428 @@ impl Machine {
                         self.machine_st.backtrack();
                     }
                 }
-                &Instruction::CallFetchGlobalVar(_) => {
+                &Instruction::CallFetchGlobalVar => {
                     self.fetch_global_var();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteFetchGlobalVar(_) => {
+                &Instruction::ExecuteFetchGlobalVar => {
                     self.fetch_global_var();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallFirstStream(_) => {
+                &Instruction::CallFirstStream => {
                     self.first_stream();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteFirstStream(_) => {
+                &Instruction::ExecuteFirstStream => {
                     self.first_stream();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallFlushOutput(_) => {
+                &Instruction::CallFlushOutput => {
                     try_or_throw!(self.machine_st, self.flush_output());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteFlushOutput(_) => {
+                &Instruction::ExecuteFlushOutput => {
                     try_or_throw!(self.machine_st, self.flush_output());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallGetByte(_) => {
+                &Instruction::CallGetByte => {
                     try_or_throw!(self.machine_st, self.get_byte());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetByte(_) => {
+                &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(_) => {
+                &Instruction::CallGetChar => {
                     try_or_throw!(self.machine_st, self.get_char());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetChar(_) => {
+                &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(_) => {
+                &Instruction::CallGetNChars => {
                     try_or_throw!(self.machine_st, self.get_n_chars());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetNChars(_) => {
+                &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(_) => {
+                &Instruction::CallGetCode => {
                     try_or_throw!(self.machine_st, self.get_code());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetCode(_) => {
+                &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(_) => {
+                &Instruction::CallGetSingleChar => {
                     try_or_throw!(self.machine_st, self.get_single_char());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetSingleChar(_) => {
+                &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::CallTruncateIfNoLiftedHeapGrowthDiff(_) => {
+                &Instruction::CallTruncateIfNoLiftedHeapGrowthDiff => {
                     self.truncate_if_no_lifted_heap_growth_diff();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteTruncateIfNoLiftedHeapGrowthDiff(_) => {
+                &Instruction::ExecuteTruncateIfNoLiftedHeapGrowthDiff => {
                     self.truncate_if_no_lifted_heap_growth_diff();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallTruncateIfNoLiftedHeapGrowth(_) => {
+                &Instruction::CallTruncateIfNoLiftedHeapGrowth => {
                     self.truncate_if_no_lifted_heap_growth();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteTruncateIfNoLiftedHeapGrowth(_) => {
+                &Instruction::ExecuteTruncateIfNoLiftedHeapGrowth => {
                     self.truncate_if_no_lifted_heap_growth();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallGetAttributedVariableList(_) => {
+                &Instruction::CallGetAttributedVariableList => {
                     self.get_attributed_variable_list();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetAttributedVariableList(_) => {
+                &Instruction::ExecuteGetAttributedVariableList => {
                     self.get_attributed_variable_list();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallGetAttrVarQueueDelimiter(_) => {
+                &Instruction::CallGetAttrVarQueueDelimiter => {
                     self.get_attr_var_queue_delimiter();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetAttrVarQueueDelimiter(_) => {
+                &Instruction::ExecuteGetAttrVarQueueDelimiter => {
                     self.get_attr_var_queue_delimiter();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallGetAttrVarQueueBeyond(_) => {
+                &Instruction::CallGetAttrVarQueueBeyond => {
                     self.get_attr_var_queue_beyond();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetAttrVarQueueBeyond(_) => {
+                &Instruction::ExecuteGetAttrVarQueueBeyond => {
                     self.get_attr_var_queue_beyond();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallGetBValue(_) => {
+                &Instruction::CallGetBValue => {
                     self.get_b_value();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetBValue(_) => {
+                &Instruction::ExecuteGetBValue => {
                     self.get_b_value();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallGetContinuationChunk(_) => {
+                &Instruction::CallGetContinuationChunk => {
                     self.get_continuation_chunk();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetContinuationChunk(_) => {
+                &Instruction::ExecuteGetContinuationChunk => {
                     self.get_continuation_chunk();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallLookupDBRef(_) => {
+                &Instruction::CallLookupDBRef => {
                     self.lookup_db_ref();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteLookupDBRef(_) => {
+                &Instruction::ExecuteLookupDBRef => {
                     self.lookup_db_ref();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallGetNextOpDBRef(_) => {
+                &Instruction::CallGetNextOpDBRef => {
                     self.get_next_op_db_ref();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetNextOpDBRef(_) => {
+                &Instruction::ExecuteGetNextOpDBRef => {
                     self.get_next_op_db_ref();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallIsPartialString(_) => {
+                &Instruction::CallIsPartialString => {
                     self.is_partial_string();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteIsPartialString(_) => {
+                &Instruction::ExecuteIsPartialString => {
                     self.is_partial_string();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallHalt(_) => {
+                &Instruction::CallHalt => {
                     self.halt();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteHalt(_) => {
+                &Instruction::ExecuteHalt => {
                     self.halt();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallGetLiftedHeapFromOffset(_) => {
+                &Instruction::CallGetLiftedHeapFromOffset => {
                     self.get_lifted_heap_from_offset();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetLiftedHeapFromOffset(_) => {
+                &Instruction::ExecuteGetLiftedHeapFromOffset => {
                     self.get_lifted_heap_from_offset();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallGetLiftedHeapFromOffsetDiff(_) => {
+                &Instruction::CallGetLiftedHeapFromOffsetDiff => {
                     self.get_lifted_heap_from_offset_diff();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetLiftedHeapFromOffsetDiff(_) => {
+                &Instruction::ExecuteGetLiftedHeapFromOffsetDiff => {
                     self.get_lifted_heap_from_offset_diff();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallGetSCCCleaner(_) => {
+                &Instruction::CallGetSCCCleaner => {
                     self.get_scc_cleaner();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetSCCCleaner(_) => {
+                &Instruction::ExecuteGetSCCCleaner => {
                     self.get_scc_cleaner();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallHeadIsDynamic(_) => {
+                &Instruction::CallHeadIsDynamic => {
                     self.head_is_dynamic();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteHeadIsDynamic(_) => {
+                &Instruction::ExecuteHeadIsDynamic => {
                     self.head_is_dynamic();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallInstallSCCCleaner(_) => {
+                &Instruction::CallInstallSCCCleaner => {
                     self.install_scc_cleaner();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteInstallSCCCleaner(_) => {
+                &Instruction::ExecuteInstallSCCCleaner => {
                     self.install_scc_cleaner();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallInstallInferenceCounter(_) => {
+                &Instruction::CallInstallInferenceCounter => {
                     try_or_throw!(self.machine_st, self.install_inference_counter());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteInstallInferenceCounter(_) => {
+                &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(_) => {
+                &Instruction::CallLiftedHeapLength => {
                     self.lifted_heap_length();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteLiftedHeapLength(_) => {
+                &Instruction::ExecuteLiftedHeapLength => {
                     self.lifted_heap_length();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallLoadLibraryAsStream(_) => {
+                &Instruction::CallLoadLibraryAsStream => {
                     try_or_throw!(self.machine_st, self.load_library_as_stream());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteLoadLibraryAsStream(_) => {
+                &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(_) => {
+                &Instruction::CallModuleExists => {
                     self.module_exists();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteModuleExists(_) => {
+                &Instruction::ExecuteModuleExists => {
                     self.module_exists();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallNextEP(_) => {
+                &Instruction::CallNextEP => {
                     self.next_ep();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteNextEP(_) => {
+                &Instruction::ExecuteNextEP => {
                     self.next_ep();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallNoSuchPredicate(_) => {
+                &Instruction::CallNoSuchPredicate => {
                     try_or_throw!(self.machine_st, self.no_such_predicate());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteNoSuchPredicate(_) => {
+                &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(_) => {
+                &Instruction::CallNumberToChars => {
                     self.number_to_chars();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteNumberToChars(_) => {
+                &Instruction::ExecuteNumberToChars => {
                     self.number_to_chars();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallNumberToCodes(_) => {
+                &Instruction::CallNumberToCodes => {
                     self.number_to_codes();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteNumberToCodes(_) => {
+                &Instruction::ExecuteNumberToCodes => {
                     self.number_to_codes();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallOpDeclaration(_) => {
+                &Instruction::CallOpDeclaration => {
                     try_or_throw!(self.machine_st, self.op_declaration());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteOpDeclaration(_) => {
+                &Instruction::ExecuteOpDeclaration => {
                     try_or_throw!(self.machine_st, self.op_declaration());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallOpen(_) => {
+                &Instruction::CallOpen => {
                     try_or_throw!(self.machine_st, self.open());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteOpen(_) => {
+                &Instruction::ExecuteOpen => {
                     try_or_throw!(self.machine_st, self.open());
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallSetStreamOptions(_) => {
+                &Instruction::CallSetStreamOptions => {
                     try_or_throw!(self.machine_st, self.set_stream_options());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteSetStreamOptions(_) => {
+                &Instruction::ExecuteSetStreamOptions => {
                     try_or_throw!(self.machine_st, self.set_stream_options());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallNextStream(_) => {
+                &Instruction::CallNextStream => {
                     self.next_stream();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteNextStream(_) => {
+                &Instruction::ExecuteNextStream => {
                     self.next_stream();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallPartialStringTail(_) => {
+                &Instruction::CallPartialStringTail => {
                     self.partial_string_tail();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePartialStringTail(_) => {
+                &Instruction::ExecutePartialStringTail => {
                     self.partial_string_tail();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallPeekByte(_) => {
+                &Instruction::CallPeekByte => {
                     try_or_throw!(self.machine_st, self.peek_byte());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePeekByte(_) => {
+                &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(_) => {
+                &Instruction::CallPeekChar => {
                     try_or_throw!(self.machine_st, self.peek_char());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePeekChar(_) => {
+                &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(_) => {
+                &Instruction::CallPeekCode => {
                     try_or_throw!(self.machine_st, self.peek_code());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePeekCode(_) => {
+                &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(_) => {
+                &Instruction::CallPointsToContinuationResetMarker => {
                     self.points_to_continuation_reset_marker();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePointsToContinuationResetMarker(_) => {
+                &Instruction::ExecutePointsToContinuationResetMarker => {
                     self.points_to_continuation_reset_marker();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallPutByte(_) => {
+                &Instruction::CallPutByte => {
                     try_or_throw!(self.machine_st, self.put_byte());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecutePutByte(_) => {
+                &Instruction::ExecutePutByte => {
                     try_or_throw!(self.machine_st, self.put_byte());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallPutChar(_) => {
+                &Instruction::CallPutChar => {
                     try_or_throw!(self.machine_st, self.put_char());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecutePutChar(_) => {
+                &Instruction::ExecutePutChar => {
                     try_or_throw!(self.machine_st, self.put_char());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallPutChars(_) => {
+                &Instruction::CallPutChars => {
                     try_or_throw!(self.machine_st, self.put_chars());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePutChars(_) => {
+                &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(_) => {
+                &Instruction::CallPutCode => {
                     try_or_throw!(self.machine_st, self.put_code());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecutePutCode(_) => {
+                &Instruction::ExecutePutCode => {
                     try_or_throw!(self.machine_st, self.put_code());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallReadQueryTerm(_) => {
+                &Instruction::CallReadQueryTerm => {
                     try_or_throw!(self.machine_st, self.read_query_term());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteReadQueryTerm(_) => {
+                &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(_) => {
+                &Instruction::CallReadTerm => {
                     try_or_throw!(self.machine_st, self.read_term());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteReadTerm(_) => {
+                &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(_) => {
+                &Instruction::CallRedoAttrVarBinding => {
                     self.redo_attr_var_binding();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteRedoAttrVarBinding(_) => {
+                &Instruction::ExecuteRedoAttrVarBinding => {
                     self.redo_attr_var_binding();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallRemoveCallPolicyCheck(_) => {
+                &Instruction::CallRemoveCallPolicyCheck => {
                     self.remove_call_policy_check();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteRemoveCallPolicyCheck(_) => {
+                &Instruction::ExecuteRemoveCallPolicyCheck => {
                     self.remove_call_policy_check();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallRemoveInferenceCounter(_) => {
+                &Instruction::CallRemoveInferenceCounter => {
                     self.remove_inference_counter();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteRemoveInferenceCounter(_) => {
+                &Instruction::ExecuteRemoveInferenceCounter => {
                     self.remove_inference_counter();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallResetContinuationMarker(_) => {
+                &Instruction::CallResetContinuationMarker => {
                     self.reset_continuation_marker();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteResetContinuationMarker(_) => {
+                &Instruction::ExecuteResetContinuationMarker => {
                     self.reset_continuation_marker();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallRestoreCutPolicy(_) => {
+                &Instruction::CallRestoreCutPolicy => {
                     self.restore_cut_policy();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteRestoreCutPolicy(_) => {
+                &Instruction::ExecuteRestoreCutPolicy => {
                     self.restore_cut_policy();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallSetCutPoint(r, _) => {
+                &Instruction::CallSetCutPoint(r) => {
                     if !self.set_cut_point(r) {
                         step_or_fail!(self, self.machine_st.p += 1);
                     }
                 }
-                &Instruction::ExecuteSetCutPoint(r, _) => {
+                &Instruction::ExecuteSetCutPoint(r) => {
                     let cp = self.machine_st.cp;
 
                     if !self.set_cut_point(r) {
@@ -4023,962 +4025,962 @@ impl Machine {
                         self.machine_st.cp = cp;
                     }
                 }
-                &Instruction::CallSetInput(_) => {
+                &Instruction::CallSetInput => {
                     try_or_throw!(self.machine_st, self.set_input());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteSetInput(_) => {
+                &Instruction::ExecuteSetInput => {
                     try_or_throw!(self.machine_st, self.set_input());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallSetOutput(_) => {
+                &Instruction::CallSetOutput => {
                     try_or_throw!(self.machine_st, self.set_output());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteSetOutput(_) => {
+                &Instruction::ExecuteSetOutput => {
                     try_or_throw!(self.machine_st, self.set_output());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallStoreBacktrackableGlobalVar(_) => {
+                &Instruction::CallStoreBacktrackableGlobalVar => {
                     self.store_backtrackable_global_var();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteStoreBacktrackableGlobalVar(_) => {
+                &Instruction::ExecuteStoreBacktrackableGlobalVar => {
                     self.store_backtrackable_global_var();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallStoreGlobalVar(_) => {
+                &Instruction::CallStoreGlobalVar => {
                     self.store_global_var();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteStoreGlobalVar(_) => {
+                &Instruction::ExecuteStoreGlobalVar => {
                     self.store_global_var();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallStreamProperty(_) => {
+                &Instruction::CallStreamProperty => {
                     try_or_throw!(self.machine_st, self.stream_property());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteStreamProperty(_) => {
+                &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(_) => {
+                &Instruction::CallSetStreamPosition => {
                     try_or_throw!(self.machine_st, self.set_stream_position());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteSetStreamPosition(_) => {
+                &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(_) => {
+                &Instruction::CallInferenceLevel => {
                     self.inference_level();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteInferenceLevel(_) => {
+                &Instruction::ExecuteInferenceLevel => {
                     self.inference_level();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCleanUpBlock(_) => {
+                &Instruction::CallCleanUpBlock => {
                     self.clean_up_block();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteCleanUpBlock(_) => {
+                &Instruction::ExecuteCleanUpBlock => {
                     self.clean_up_block();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallFail(_) | &Instruction::ExecuteFail(_) => {
+                &Instruction::CallFail | &Instruction::ExecuteFail => {
                     self.machine_st.backtrack();
                 }
-                &Instruction::CallGetBall(_) => {
+                &Instruction::CallGetBall => {
                     self.get_ball();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetBall(_) => {
+                &Instruction::ExecuteGetBall => {
                     self.get_ball();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallGetCurrentBlock(_) => {
+                &Instruction::CallGetCurrentBlock => {
                     self.get_current_block();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetCurrentBlock(_) => {
+                &Instruction::ExecuteGetCurrentBlock => {
                     self.get_current_block();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallGetCutPoint(_) => {
+                &Instruction::CallGetCutPoint => {
                     self.get_cut_point();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetCutPoint(_) => {
+                &Instruction::ExecuteGetCutPoint => {
                     self.get_cut_point();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallGetDoubleQuotes(_) => {
+                &Instruction::CallGetDoubleQuotes => {
                     self.get_double_quotes();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetDoubleQuotes(_) => {
+                &Instruction::ExecuteGetDoubleQuotes => {
                     self.get_double_quotes();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallInstallNewBlock(_) => {
+                &Instruction::CallInstallNewBlock => {
                     self.machine_st.install_new_block(self.machine_st.registers[1]);
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteInstallNewBlock(_) => {
+                &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(_) => {
+                &Instruction::CallMaybe => {
                     self.maybe();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteMaybe(_) => {
+                &Instruction::ExecuteMaybe => {
                     self.maybe();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCpuNow(_) => {
+                &Instruction::CallCpuNow => {
                     self.cpu_now();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCpuNow(_) => {
+                &Instruction::ExecuteCpuNow => {
                     self.cpu_now();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallDeterministicLengthRundown(_) => {
+                &Instruction::CallDeterministicLengthRundown => {
                     try_or_throw!(self.machine_st, self.det_length_rundown());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteDeterministicLengthRundown(_) => {
+                &Instruction::ExecuteDeterministicLengthRundown => {
                     try_or_throw!(self.machine_st, self.det_length_rundown());
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallHttpOpen(_) => {
+                &Instruction::CallHttpOpen => {
                     try_or_throw!(self.machine_st, self.http_open());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteHttpOpen(_) => {
+                &Instruction::ExecuteHttpOpen => {
                     try_or_throw!(self.machine_st, self.http_open());
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-               &Instruction::CallHttpListen(_) => {
+               &Instruction::CallHttpListen => {
                    try_or_throw!(self.machine_st, self.http_listen());
                    step_or_fail!(self, self.machine_st.p += 1);
                }
-               &Instruction::ExecuteHttpListen(_) => {
+               &Instruction::ExecuteHttpListen => {
                    try_or_throw!(self.machine_st, self.http_listen());
                    step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                }
-               &Instruction::CallHttpAccept(_) => {
+               &Instruction::CallHttpAccept => {
                    try_or_throw!(self.machine_st, self.http_accept());
                    step_or_fail!(self, self.machine_st.p += 1);
                }
-               &Instruction::ExecuteHttpAccept(_) => {
+               &Instruction::ExecuteHttpAccept => {
                    try_or_throw!(self.machine_st, self.http_accept());
                    step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                }
-               &Instruction::CallHttpAnswer(_) => {
+               &Instruction::CallHttpAnswer => {
                    try_or_throw!(self.machine_st, self.http_answer());
                    step_or_fail!(self, self.machine_st.p += 1);
                }
-               &Instruction::ExecuteHttpAnswer(_) => {
+               &Instruction::ExecuteHttpAnswer => {
                    try_or_throw!(self.machine_st, self.http_answer());
                    step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                }
-               &Instruction::CallLoadForeignLib(_) => {
+               &Instruction::CallLoadForeignLib => {
                    try_or_throw!(self.machine_st, self.load_foreign_lib());
                    step_or_fail!(self, self.machine_st.p += 1);
                }
-               &Instruction::ExecuteLoadForeignLib(_) => {
+               &Instruction::ExecuteLoadForeignLib => {
                    try_or_throw!(self.machine_st, self.load_foreign_lib());
                    step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                }
-               &Instruction::CallForeignCall(_) => {
+               &Instruction::CallForeignCall => {
                    try_or_throw!(self.machine_st, self.foreign_call());
                    step_or_fail!(self, self.machine_st.p += 1);
                }
-               &Instruction::ExecuteForeignCall(_) => {
+               &Instruction::ExecuteForeignCall => {
                    try_or_throw!(self.machine_st, self.foreign_call());
                    step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                }
-               &Instruction::CallDefineForeignStruct(_) => {
+               &Instruction::CallDefineForeignStruct => {
                    try_or_throw!(self.machine_st, self.define_foreign_struct());
                    step_or_fail!(self, self.machine_st.p += 1);
                }
-               &Instruction::ExecuteDefineForeignStruct(_) => {
+               &Instruction::ExecuteDefineForeignStruct => {
                    try_or_throw!(self.machine_st, self.define_foreign_struct());
                    step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                }
-                &Instruction::CallCurrentTime(_) => {
+                &Instruction::CallCurrentTime => {
                     self.current_time();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCurrentTime(_) => {
+                &Instruction::ExecuteCurrentTime => {
                     self.current_time();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallQuotedToken(_) => {
+                &Instruction::CallQuotedToken => {
                     self.quoted_token();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteQuotedToken(_) => {
+                &Instruction::ExecuteQuotedToken => {
                     self.quoted_token();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallReadTermFromChars(_) => {
+                &Instruction::CallReadTermFromChars => {
                     try_or_throw!(self.machine_st, self.read_term_from_chars());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteReadTermFromChars(_) => {
+                &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(_) => {
+                &Instruction::CallResetBlock => {
                     self.reset_block();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteResetBlock(_) => {
+                &Instruction::ExecuteResetBlock => {
                     self.reset_block();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallReturnFromVerifyAttr(_) |
-                &Instruction::ExecuteReturnFromVerifyAttr(_) => {
+                &Instruction::CallReturnFromVerifyAttr |
+                &Instruction::ExecuteReturnFromVerifyAttr => {
                     self.return_from_verify_attr();
                 }
-                &Instruction::CallSetBall(_) => {
+                &Instruction::CallSetBall => {
                     self.set_ball();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteSetBall(_) => {
+                &Instruction::ExecuteSetBall => {
                     self.set_ball();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallPushBallStack(_) => {
+                &Instruction::CallPushBallStack => {
                     self.push_ball_stack();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePushBallStack(_) => {
+                &Instruction::ExecutePushBallStack => {
                     self.push_ball_stack();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallPopBallStack(_) => {
+                &Instruction::CallPopBallStack => {
                     self.pop_ball_stack();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecutePopBallStack(_) => {
+                &Instruction::ExecutePopBallStack => {
                     self.pop_ball_stack();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallPopFromBallStack(_) => {
+                &Instruction::CallPopFromBallStack => {
                     self.pop_from_ball_stack();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecutePopFromBallStack(_) => {
+                &Instruction::ExecutePopFromBallStack => {
                     self.pop_from_ball_stack();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallSetCutPointByDefault(r, _) => {
+                &Instruction::CallSetCutPointByDefault(r) => {
                     self.set_cut_point_by_default(r);
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteSetCutPointByDefault(r, _) => {
+                &Instruction::ExecuteSetCutPointByDefault(r) => {
                     self.set_cut_point_by_default(r);
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallSetDoubleQuotes(_) => {
+                &Instruction::CallSetDoubleQuotes => {
                     self.set_double_quotes();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteSetDoubleQuotes(_) => {
+                &Instruction::ExecuteSetDoubleQuotes => {
                     self.set_double_quotes();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallSetSeed(_) => {
+                &Instruction::CallSetSeed => {
                     self.set_seed();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteSetSeed(_) => {
+                &Instruction::ExecuteSetSeed => {
                     self.set_seed();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallSkipMaxList(_) => {
+                &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(_) => {
+                &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(_) => {
+                &Instruction::CallSleep => {
                     self.sleep();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteSleep(_) => {
+                &Instruction::ExecuteSleep => {
                     self.sleep();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallSocketClientOpen(_) => {
+                &Instruction::CallSocketClientOpen => {
                     try_or_throw!(self.machine_st, self.socket_client_open());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteSocketClientOpen(_) => {
+                &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(_) => {
+                &Instruction::CallSocketServerOpen => {
                     try_or_throw!(self.machine_st, self.socket_server_open());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteSocketServerOpen(_) => {
+                &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(_) => {
+                &Instruction::CallSocketServerAccept => {
                     try_or_throw!(self.machine_st, self.socket_server_accept());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteSocketServerAccept(_) => {
+                &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(_) => {
+                &Instruction::CallSocketServerClose => {
                     try_or_throw!(self.machine_st, self.socket_server_close());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteSocketServerClose(_) => {
+                &Instruction::ExecuteSocketServerClose => {
                     try_or_throw!(self.machine_st, self.socket_server_close());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallTLSAcceptClient(_) => {
+                &Instruction::CallTLSAcceptClient => {
                     try_or_throw!(self.machine_st, self.tls_accept_client());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteTLSAcceptClient(_) => {
+                &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(_) => {
+                &Instruction::CallTLSClientConnect => {
                     try_or_throw!(self.machine_st, self.tls_client_connect());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteTLSClientConnect(_) => {
+                &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(_) => {
+                &Instruction::CallSucceed => {
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteSucceed(_) => {
+                &Instruction::ExecuteSucceed => {
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallTermAttributedVariables(_) => {
+                &Instruction::CallTermAttributedVariables => {
                     self.term_attributed_variables();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteTermAttributedVariables(_) => {
+                &Instruction::ExecuteTermAttributedVariables => {
                     self.term_attributed_variables();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallTermVariables(_) => {
+                &Instruction::CallTermVariables => {
                     self.term_variables();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteTermVariables(_) => {
+                &Instruction::ExecuteTermVariables => {
                     self.term_variables();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallTermVariablesUnderMaxDepth(_) => {
+                &Instruction::CallTermVariablesUnderMaxDepth => {
                     self.term_variables_under_max_depth();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteTermVariablesUnderMaxDepth(_) => {
+                &Instruction::ExecuteTermVariablesUnderMaxDepth => {
                     self.term_variables_under_max_depth();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallTruncateLiftedHeapTo(_) => {
+                &Instruction::CallTruncateLiftedHeapTo => {
                     self.truncate_lifted_heap_to();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteTruncateLiftedHeapTo(_) => {
+                &Instruction::ExecuteTruncateLiftedHeapTo => {
                     self.truncate_lifted_heap_to();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallUnifyWithOccursCheck(_) => {
+                &Instruction::CallUnifyWithOccursCheck => {
                     self.unify_with_occurs_check();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteUnifyWithOccursCheck(_) => {
+                &Instruction::ExecuteUnifyWithOccursCheck => {
                     self.unify_with_occurs_check();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallUnwindEnvironments(_) => {
+                &Instruction::CallUnwindEnvironments => {
                     if !self.unwind_environments() {
                         self.machine_st.p += 1;
                     }
                 }
-                &Instruction::ExecuteUnwindEnvironments(_) => {
+                &Instruction::ExecuteUnwindEnvironments => {
                     if !self.unwind_environments() {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
-                &Instruction::CallUnwindStack(_) | &Instruction::ExecuteUnwindStack(_) => {
+                &Instruction::CallUnwindStack | &Instruction::ExecuteUnwindStack => {
                     self.machine_st.unwind_stack();
                     self.machine_st.backtrack();
                 }
-                &Instruction::CallWAMInstructions(_) => {
+                &Instruction::CallWAMInstructions => {
                     try_or_throw!(self.machine_st, self.wam_instructions());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteWAMInstructions(_) => {
+                &Instruction::ExecuteWAMInstructions => {
                     try_or_throw!(self.machine_st, self.wam_instructions());
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallInlinedInstructions(_) => {
+                &Instruction::CallInlinedInstructions => {
                     self.inlined_instructions();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteInlinedInstructions(_) => {
+                &Instruction::ExecuteInlinedInstructions => {
                     self.inlined_instructions();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallWriteTerm(_) => {
+                &Instruction::CallWriteTerm => {
                     try_or_throw!(self.machine_st, self.write_term());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteWriteTerm(_) => {
+                &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(_) => {
+                &Instruction::CallWriteTermToChars => {
                     try_or_throw!(self.machine_st, self.write_term_to_chars());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteWriteTermToChars(_) => {
+                &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(_) => {
+                &Instruction::CallScryerPrologVersion => {
                     self.scryer_prolog_version();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteScryerPrologVersion(_) => {
+                &Instruction::ExecuteScryerPrologVersion => {
                     self.scryer_prolog_version();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCryptoRandomByte(_) => {
+                &Instruction::CallCryptoRandomByte => {
                     self.crypto_random_byte();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCryptoRandomByte(_) => {
+                &Instruction::ExecuteCryptoRandomByte => {
                     self.crypto_random_byte();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCryptoDataHash(_) => {
+                &Instruction::CallCryptoDataHash => {
                     self.crypto_data_hash();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCryptoDataHash(_) => {
+                &Instruction::ExecuteCryptoDataHash => {
                     self.crypto_data_hash();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCryptoDataHKDF(_) => {
+                &Instruction::CallCryptoDataHKDF => {
                     self.crypto_data_hkdf();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCryptoDataHKDF(_) => {
+                &Instruction::ExecuteCryptoDataHKDF => {
                     self.crypto_data_hkdf();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCryptoPasswordHash(_) => {
+                &Instruction::CallCryptoPasswordHash => {
                     self.crypto_password_hash();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCryptoPasswordHash(_) => {
+                &Instruction::ExecuteCryptoPasswordHash => {
                     self.crypto_password_hash();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCryptoDataEncrypt(_) => {
+                &Instruction::CallCryptoDataEncrypt => {
                     self.crypto_data_encrypt();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCryptoDataEncrypt(_) => {
+                &Instruction::ExecuteCryptoDataEncrypt => {
                     self.crypto_data_encrypt();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCryptoDataDecrypt(_) => {
+                &Instruction::CallCryptoDataDecrypt => {
                     self.crypto_data_decrypt();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCryptoDataDecrypt(_) => {
+                &Instruction::ExecuteCryptoDataDecrypt => {
                     self.crypto_data_decrypt();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCryptoCurveScalarMult(_) => {
+                &Instruction::CallCryptoCurveScalarMult => {
                     self.crypto_curve_scalar_mult();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCryptoCurveScalarMult(_) => {
+                &Instruction::ExecuteCryptoCurveScalarMult => {
                     self.crypto_curve_scalar_mult();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallEd25519Sign(_) => {
+                &Instruction::CallEd25519Sign => {
                     self.ed25519_sign();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteEd25519Sign(_) => {
+                &Instruction::ExecuteEd25519Sign => {
                     self.ed25519_sign();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallEd25519Verify(_) => {
+                &Instruction::CallEd25519Verify => {
                     self.ed25519_verify();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteEd25519Verify(_) => {
+                &Instruction::ExecuteEd25519Verify => {
                     self.ed25519_verify();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallEd25519NewKeyPair(_) => {
+                &Instruction::CallEd25519NewKeyPair => {
                     self.ed25519_new_key_pair();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteEd25519NewKeyPair(_) => {
+                &Instruction::ExecuteEd25519NewKeyPair => {
                     self.ed25519_new_key_pair();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallEd25519KeyPairPublicKey(_) => {
+                &Instruction::CallEd25519KeyPairPublicKey => {
                     self.ed25519_key_pair_public_key();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteEd25519KeyPairPublicKey(_) => {
+                &Instruction::ExecuteEd25519KeyPairPublicKey => {
                     self.ed25519_key_pair_public_key();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCurve25519ScalarMult(_) => {
+                &Instruction::CallCurve25519ScalarMult => {
                     self.curve25519_scalar_mult();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCurve25519ScalarMult(_) => {
+                &Instruction::ExecuteCurve25519ScalarMult => {
                     self.curve25519_scalar_mult();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallFirstNonOctet(_) => {
+                &Instruction::CallFirstNonOctet => {
                     self.first_non_octet();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteFirstNonOctet(_) => {
+                &Instruction::ExecuteFirstNonOctet => {
                     self.first_non_octet();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallLoadHTML(_) => {
+                &Instruction::CallLoadHTML => {
                     self.load_html();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteLoadHTML(_) => {
+                &Instruction::ExecuteLoadHTML => {
                     self.load_html();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallLoadXML(_) => {
+                &Instruction::CallLoadXML => {
                     self.load_xml();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteLoadXML(_) => {
+                &Instruction::ExecuteLoadXML => {
                     self.load_xml();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallGetEnv(_) => {
+                &Instruction::CallGetEnv => {
                     self.get_env();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetEnv(_) => {
+                &Instruction::ExecuteGetEnv => {
                     self.get_env();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallSetEnv(_) => {
+                &Instruction::CallSetEnv => {
                     self.set_env();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteSetEnv(_) => {
+                &Instruction::ExecuteSetEnv => {
                     self.set_env();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallUnsetEnv(_) => {
+                &Instruction::CallUnsetEnv => {
                     self.unset_env();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteUnsetEnv(_) => {
+                &Instruction::ExecuteUnsetEnv => {
                     self.unset_env();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallShell(_) => {
+                &Instruction::CallShell => {
                     self.shell();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteShell(_) => {
+                &Instruction::ExecuteShell => {
                     self.shell();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallPID(_) => {
+                &Instruction::CallPID => {
                     self.pid();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePID(_) => {
+                &Instruction::ExecutePID => {
                     self.pid();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCharsBase64(_) => {
+                &Instruction::CallCharsBase64 => {
                     try_or_throw!(self.machine_st, self.chars_base64());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCharsBase64(_) => {
+                &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(_) => {
+                &Instruction::CallDevourWhitespace => {
                     try_or_throw!(self.machine_st, self.devour_whitespace());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteDevourWhitespace(_) => {
+                &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(_) => {
+                &Instruction::CallIsSTOEnabled => {
                     self.is_sto_enabled();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteIsSTOEnabled(_) => {
+                &Instruction::ExecuteIsSTOEnabled => {
                     self.is_sto_enabled();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallSetSTOAsUnify(_) => {
+                &Instruction::CallSetSTOAsUnify => {
                     self.set_sto_as_unify();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteSetSTOAsUnify(_) => {
+                &Instruction::ExecuteSetSTOAsUnify => {
                     self.set_sto_as_unify();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallSetNSTOAsUnify(_) => {
+                &Instruction::CallSetNSTOAsUnify => {
                     self.set_nsto_as_unify();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteSetNSTOAsUnify(_) => {
+                &Instruction::ExecuteSetNSTOAsUnify => {
                     self.set_nsto_as_unify();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallSetSTOWithErrorAsUnify(_) => {
+                &Instruction::CallSetSTOWithErrorAsUnify => {
                     self.set_sto_with_error_as_unify();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteSetSTOWithErrorAsUnify(_) => {
+                &Instruction::ExecuteSetSTOWithErrorAsUnify => {
                     self.set_sto_with_error_as_unify();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallHomeDirectory(_) => {
+                &Instruction::CallHomeDirectory => {
                     self.home_directory();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteHomeDirectory(_) => {
+                &Instruction::ExecuteHomeDirectory => {
                     self.home_directory();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallDebugHook(_) => {
+                &Instruction::CallDebugHook => {
                     self.debug_hook();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteDebugHook(_) => {
+                &Instruction::ExecuteDebugHook => {
                     self.debug_hook();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallPopCount(_) => {
+                &Instruction::CallPopCount => {
                     self.pop_count();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePopCount(_) => {
+                &Instruction::ExecutePopCount => {
                     self.pop_count();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallAddDiscontiguousPredicate(_) => {
+                &Instruction::CallAddDiscontiguousPredicate => {
                     try_or_throw!(self.machine_st, self.add_discontiguous_predicate());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteAddDiscontiguousPredicate(_) => {
+                &Instruction::ExecuteAddDiscontiguousPredicate => {
                     try_or_throw!(self.machine_st, self.add_discontiguous_predicate());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallAddDynamicPredicate(_) => {
+                &Instruction::CallAddDynamicPredicate => {
                     try_or_throw!(self.machine_st, self.add_dynamic_predicate());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteAddDynamicPredicate(_) => {
+                &Instruction::ExecuteAddDynamicPredicate => {
                     try_or_throw!(self.machine_st, self.add_dynamic_predicate());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallAddMultifilePredicate(_) => {
+                &Instruction::CallAddMultifilePredicate => {
                     try_or_throw!(self.machine_st, self.add_multifile_predicate());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteAddMultifilePredicate(_) => {
+                &Instruction::ExecuteAddMultifilePredicate => {
                     try_or_throw!(self.machine_st, self.add_multifile_predicate());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallAddGoalExpansionClause(_) => {
+                &Instruction::CallAddGoalExpansionClause => {
                     try_or_throw!(self.machine_st, self.add_goal_expansion_clause());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteAddGoalExpansionClause(_) => {
+                &Instruction::ExecuteAddGoalExpansionClause => {
                     try_or_throw!(self.machine_st, self.add_goal_expansion_clause());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallAddTermExpansionClause(_) => {
+                &Instruction::CallAddTermExpansionClause => {
                     try_or_throw!(self.machine_st, self.add_term_expansion_clause());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteAddTermExpansionClause(_) => {
+                &Instruction::ExecuteAddTermExpansionClause => {
                     try_or_throw!(self.machine_st, self.add_term_expansion_clause());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallAddInSituFilenameModule(_) => {
+                &Instruction::CallAddInSituFilenameModule => {
                     try_or_throw!(self.machine_st, self.add_in_situ_filename_module());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteAddInSituFilenameModule(_) => {
+                &Instruction::ExecuteAddInSituFilenameModule => {
                     try_or_throw!(self.machine_st, self.add_in_situ_filename_module());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallClauseToEvacuable(_) => {
+                &Instruction::CallClauseToEvacuable => {
                     try_or_throw!(self.machine_st, self.clause_to_evacuable());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteClauseToEvacuable(_) => {
+                &Instruction::ExecuteClauseToEvacuable => {
                     try_or_throw!(self.machine_st, self.clause_to_evacuable());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallScopedClauseToEvacuable(_) => {
+                &Instruction::CallScopedClauseToEvacuable => {
                     try_or_throw!(self.machine_st, self.scoped_clause_to_evacuable());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteScopedClauseToEvacuable(_) => {
+                &Instruction::ExecuteScopedClauseToEvacuable => {
                     try_or_throw!(self.machine_st, self.scoped_clause_to_evacuable());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallConcludeLoad(_) => {
+                &Instruction::CallConcludeLoad => {
                     try_or_throw!(self.machine_st, self.conclude_load());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteConcludeLoad(_) => {
+                &Instruction::ExecuteConcludeLoad => {
                     try_or_throw!(self.machine_st, self.conclude_load());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallDeclareModule(_) => {
+                &Instruction::CallDeclareModule => {
                     try_or_throw!(self.machine_st, self.declare_module());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteDeclareModule(_) => {
+                &Instruction::ExecuteDeclareModule => {
                     try_or_throw!(self.machine_st, self.declare_module());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallLoadCompiledLibrary(_) => {
+                &Instruction::CallLoadCompiledLibrary => {
                     try_or_throw!(self.machine_st, self.load_compiled_library());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteLoadCompiledLibrary(_) => {
+                &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(_) => {
+                &Instruction::CallLoadContextSource => {
                     self.load_context_source();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteLoadContextSource(_) => {
+                &Instruction::ExecuteLoadContextSource => {
                     self.load_context_source();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallLoadContextFile(_) => {
+                &Instruction::CallLoadContextFile => {
                     self.load_context_file();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteLoadContextFile(_) => {
+                &Instruction::ExecuteLoadContextFile => {
                     self.load_context_file();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallLoadContextDirectory(_) => {
+                &Instruction::CallLoadContextDirectory => {
                     self.load_context_directory();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteLoadContextDirectory(_) => {
+                &Instruction::ExecuteLoadContextDirectory => {
                     self.load_context_directory();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallLoadContextModule(_) => {
+                &Instruction::CallLoadContextModule => {
                     self.load_context_module(self.machine_st.registers[1]);
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteLoadContextModule(_) => {
+                &Instruction::ExecuteLoadContextModule => {
                     self.load_context_module(self.machine_st.registers[1]);
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallLoadContextStream(_) => {
+                &Instruction::CallLoadContextStream => {
                     self.load_context_stream();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteLoadContextStream(_) => {
+                &Instruction::ExecuteLoadContextStream => {
                     self.load_context_stream();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallPopLoadContext(_) => {
+                &Instruction::CallPopLoadContext => {
                     self.pop_load_context();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecutePopLoadContext(_) => {
+                &Instruction::ExecutePopLoadContext => {
                     self.pop_load_context();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallPopLoadStatePayload(_) => {
+                &Instruction::CallPopLoadStatePayload => {
                     self.pop_load_state_payload();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecutePopLoadStatePayload(_) => {
+                &Instruction::ExecutePopLoadStatePayload => {
                     self.pop_load_state_payload();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallPushLoadContext(_) => {
+                &Instruction::CallPushLoadContext => {
                     try_or_throw!(self.machine_st, self.push_load_context());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecutePushLoadContext(_) => {
+                &Instruction::ExecutePushLoadContext => {
                     try_or_throw!(self.machine_st, self.push_load_context());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallPushLoadStatePayload(_) => {
+                &Instruction::CallPushLoadStatePayload => {
                     self.push_load_state_payload();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePushLoadStatePayload(_) => {
+                &Instruction::ExecutePushLoadStatePayload => {
                     self.push_load_state_payload();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallUseModule(_) => {
+                &Instruction::CallUseModule => {
                     try_or_throw!(self.machine_st, self.use_module());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteUseModule(_) => {
+                &Instruction::ExecuteUseModule => {
                     try_or_throw!(self.machine_st, self.use_module());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallBuiltInProperty(_) => {
+                &Instruction::CallBuiltInProperty => {
                     self.builtin_property();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteBuiltInProperty(_) => {
+                &Instruction::ExecuteBuiltInProperty => {
                     self.builtin_property();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallMetaPredicateProperty(_) => {
+                &Instruction::CallMetaPredicateProperty => {
                     self.meta_predicate_property();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteMetaPredicateProperty(_) => {
+                &Instruction::ExecuteMetaPredicateProperty => {
                     self.meta_predicate_property();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallMultifileProperty(_) => {
+                &Instruction::CallMultifileProperty => {
                     self.multifile_property();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteMultifileProperty(_) => {
+                &Instruction::ExecuteMultifileProperty => {
                     self.multifile_property();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallDiscontiguousProperty(_) => {
+                &Instruction::CallDiscontiguousProperty => {
                     self.discontiguous_property();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteDiscontiguousProperty(_) => {
+                &Instruction::ExecuteDiscontiguousProperty => {
                     self.discontiguous_property();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallDynamicProperty(_) => {
+                &Instruction::CallDynamicProperty => {
                     self.dynamic_property();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteDynamicProperty(_) => {
+                &Instruction::ExecuteDynamicProperty => {
                     self.dynamic_property();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallAbolishClause(_) => {
+                &Instruction::CallAbolishClause => {
                     try_or_throw!(self.machine_st, self.abolish_clause());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteAbolishClause(_) => {
+                &Instruction::ExecuteAbolishClause => {
                     try_or_throw!(self.machine_st, self.abolish_clause());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallAsserta(_) => {
+                &Instruction::CallAsserta => {
                     try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Prepend));
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteAsserta(_) => {
+                &Instruction::ExecuteAsserta => {
                     try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Prepend));
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallAssertz(_) => {
+                &Instruction::CallAssertz => {
                     try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Append));
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteAssertz(_) => {
+                &Instruction::ExecuteAssertz => {
                     try_or_throw!(self.machine_st, self.compile_assert(AppendOrPrepend::Append));
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallRetract(_) => {
+                &Instruction::CallRetract => {
                     try_or_throw!(self.machine_st, self.retract_clause());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteRetract(_) => {
+                &Instruction::ExecuteRetract => {
                     try_or_throw!(self.machine_st, self.retract_clause());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallIsConsistentWithTermQueue(_) => {
+                &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(_) => {
+                &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(_) => {
+                &Instruction::CallFlushTermQueue => {
                     try_or_throw!(self.machine_st, self.flush_term_queue());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteFlushTermQueue(_) => {
+                &Instruction::ExecuteFlushTermQueue => {
                     try_or_throw!(self.machine_st, self.flush_term_queue());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallRemoveModuleExports(_) => {
+                &Instruction::CallRemoveModuleExports => {
                     try_or_throw!(self.machine_st, self.remove_module_exports());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteRemoveModuleExports(_) => {
+                &Instruction::ExecuteRemoveModuleExports => {
                     try_or_throw!(self.machine_st, self.remove_module_exports());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallAddNonCountedBacktracking(_) => {
+                &Instruction::CallAddNonCountedBacktracking => {
                     try_or_throw!(self.machine_st, self.add_non_counted_backtracking());
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteAddNonCountedBacktracking(_) => {
+                &Instruction::ExecuteAddNonCountedBacktracking => {
                     try_or_throw!(self.machine_st, self.add_non_counted_backtracking());
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallPredicateDefined(_) => {
+                &Instruction::CallPredicateDefined => {
                     self.machine_st.fail = !self.predicate_defined();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePredicateDefined(_) => {
+                &Instruction::ExecutePredicateDefined => {
                     self.machine_st.fail = !self.predicate_defined();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallStripModule(_) => {
+                &Instruction::CallStripModule => {
                     let (module_loc, qualified_goal) = self.machine_st.strip_module(
                         self.machine_st.registers[1],
                         self.machine_st.registers[2],
@@ -5002,7 +5004,7 @@ impl Machine {
 
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteStripModule(_) => {
+                &Instruction::ExecuteStripModule => {
                     let (module_loc, qualified_goal) = self.machine_st.strip_module(
                         self.machine_st.registers[1],
                         self.machine_st.registers[2],
@@ -5026,31 +5028,31 @@ impl Machine {
 
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallPrepareCallClause(arity, _) => {
+                &Instruction::CallPrepareCallClause(arity) => {
                     try_or_throw!(self.machine_st, self.prepare_call_clause(arity));
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePrepareCallClause(arity, _) => {
+                &Instruction::ExecutePrepareCallClause(arity) => {
                     try_or_throw!(self.machine_st, self.prepare_call_clause(arity));
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallCompileInlineOrExpandedGoal(_) => {
+                &Instruction::CallCompileInlineOrExpandedGoal => {
                     try_or_throw!(self.machine_st, self.compile_inline_or_expanded_goal());
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteCompileInlineOrExpandedGoal(_) => {
+                &Instruction::ExecuteCompileInlineOrExpandedGoal => {
                     try_or_throw!(self.machine_st, self.compile_inline_or_expanded_goal());
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallIsExpandedOrInlined(_) => {
+                &Instruction::CallIsExpandedOrInlined => {
                     self.machine_st.fail = !self.is_expanded_or_inlined();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteIsExpandedOrInlined(_) => {
+                &Instruction::ExecuteIsExpandedOrInlined => {
                     self.machine_st.fail = !self.is_expanded_or_inlined();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallInlineCallN(arity, _) => {
+                &Instruction::CallInlineCallN(arity) => {
                     let call_at_index = |wam: &mut Machine, name, arity, ptr| {
                         wam.try_call(name, arity, ptr)
                     };
@@ -5066,7 +5068,7 @@ impl Machine {
                         );
                     }
                 }
-                &Instruction::ExecuteInlineCallN(arity, _) => {
+                &Instruction::ExecuteInlineCallN(arity) => {
                     let call_at_index = |wam: &mut Machine, name, arity, ptr| {
                         wam.try_execute(name, arity, ptr)
                     };
@@ -5082,7 +5084,7 @@ impl Machine {
                         );
                     }
                 }
-                &Instruction::CallGetClauseP(_) => {
+                &Instruction::CallGetClauseP => {
                     let module_name = cell_as_atom!(self.deref_register(3));
 
                     let (n, p) = self.get_clause_p(module_name);
@@ -5098,7 +5100,7 @@ impl Machine {
 
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetClauseP(_) => {
+                &Instruction::ExecuteGetClauseP => {
                     let module_name = cell_as_atom!(self.deref_register(3));
 
                     let (n, p) = self.get_clause_p(module_name);
@@ -5114,7 +5116,7 @@ impl Machine {
 
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallInvokeClauseAtP(_) => {
+                &Instruction::CallInvokeClauseAtP => {
                     let key_cell = self.machine_st.registers[1];
                     let key = self.machine_st.name_and_arity_from_heap(key_cell).unwrap();
 
@@ -5159,7 +5161,7 @@ impl Machine {
 
                     self.machine_st.call_at_index(2, p);
                 }
-                &Instruction::ExecuteInvokeClauseAtP(_) => {
+                &Instruction::ExecuteInvokeClauseAtP => {
                     let key_cell = self.machine_st.registers[1];
                     let key = self.machine_st.name_and_arity_from_heap(key_cell).unwrap();
 
@@ -5204,51 +5206,51 @@ impl Machine {
 
                     self.machine_st.execute_at_index(2, p);
                 }
-                &Instruction::CallGetFromAttributedVarList(_) => {
+                &Instruction::CallGetFromAttributedVarList => {
                     self.get_from_attributed_variable_list();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetFromAttributedVarList(_) => {
+                &Instruction::ExecuteGetFromAttributedVarList => {
                     self.get_from_attributed_variable_list();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallPutToAttributedVarList(_) => {
+                &Instruction::CallPutToAttributedVarList => {
                     self.put_to_attributed_variable_list();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecutePutToAttributedVarList(_) => {
+                &Instruction::ExecutePutToAttributedVarList => {
                     self.put_to_attributed_variable_list();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallDeleteFromAttributedVarList(_) => {
+                &Instruction::CallDeleteFromAttributedVarList => {
                     self.delete_from_attributed_variable_list();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteDeleteFromAttributedVarList(_) => {
+                &Instruction::ExecuteDeleteFromAttributedVarList => {
                     self.delete_from_attributed_variable_list();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
-                &Instruction::CallDeleteAllAttributesFromVar(_) => {
+                &Instruction::CallDeleteAllAttributesFromVar => {
                     self.delete_all_attributes_from_var();
                     self.machine_st.p += 1;
                 }
-                &Instruction::ExecuteDeleteAllAttributesFromVar(_) => {
+                &Instruction::ExecuteDeleteAllAttributesFromVar => {
                     self.delete_all_attributes_from_var();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallUnattributedVar(_) => {
+                &Instruction::CallUnattributedVar => {
                     self.machine_st.unattributed_var();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteUnattributedVar(_) => {
+                &Instruction::ExecuteUnattributedVar => {
                     self.machine_st.unattributed_var();
                     self.machine_st.p = self.machine_st.cp;
                 }
-                &Instruction::CallGetDBRefs(_) => {
+                &Instruction::CallGetDBRefs => {
                     self.get_db_refs();
                     step_or_fail!(self, self.machine_st.p += 1);
                 }
-                &Instruction::ExecuteGetDBRefs(_) => {
+                &Instruction::ExecuteGetDBRefs => {
                     self.get_db_refs();
                     step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
                 }
index 3d0a638a8c3cbd1859a3ef823516ceb2493de262..56aa88eb5e978cc8942356f47d0b933c1a5d4868 100644 (file)
@@ -444,10 +444,8 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
         let tl = preprocessor.try_term_to_tl(self, term)?;
 
         Ok(match tl {
-            TopLevel::Fact(fact) => PredicateClause::Fact(fact),
-            TopLevel::Rule(rule) => PredicateClause::Rule(rule),
-            TopLevel::Query(_) => return Err(SessionError::QueryCannotBeDefinedAsFact),
-            _ => unreachable!(),
+            TopLevel::Fact(fact, var_data) => PredicateClause::Fact(fact, var_data),
+            TopLevel::Rule(rule, var_data) => PredicateClause::Rule(rule, var_data),
         })
     }
 
index bb093a0e979984927e2f3c9d9b034ec31da4076f..51815c7ec838bcd77b1313c74e6c65f22a9d0cde 100644 (file)
@@ -1428,7 +1428,7 @@ impl MachineState {
                     }
                 }
                 (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar, h) => {
-                    term_stack.push(Term::Var(Cell::default(), Var::Generated(h)));
+                    term_stack.push(Term::Var(Cell::default(), VarPtr::from(format!("_{}", h))));
                 }
                 (HeapCellValueTag::Cons | HeapCellValueTag::CStr | HeapCellValueTag::Fixnum |
                  HeapCellValueTag::Char | HeapCellValueTag::F64) => {
index afa2bea2b5966d86b93d7d47b5e670d541b2d66b..fdc60e0b90c3f354bffa80976fbf04ab8c089b24 100644 (file)
@@ -2,7 +2,6 @@ use crate::parser::ast::*;
 
 use crate::arena::*;
 use crate::atom_table::*;
-use crate::fixtures::*;
 use crate::forms::*;
 use crate::machine::loader::*;
 use crate::machine::machine_state::*;
@@ -227,8 +226,8 @@ impl CodeIndex {
     }
 }
 
-pub(crate) type HeapVarDict = IndexMap<Var, HeapCellValue, FxBuildHasher>;
-pub(crate) type AllocVarDict = IndexMap<Var, VarAlloc, FxBuildHasher>;
+pub(crate) type HeapVarDict = IndexMap<VarPtr, HeapCellValue, FxBuildHasher>;
+// pub(crate) type AllocVarDict = IndexMap<Var, VarAlloc, FxBuildHasher>;
 
 pub(crate) type GlobalVarDir = IndexMap<Atom, (Ball, Option<HeapCellValue>), FxBuildHasher>;
 
index 6d0de7d9af18c2a159f3f5b79a6ea9a33801b195..26d0309b043a4fb5c40a21c818fbb31860a87093 100644 (file)
@@ -500,13 +500,13 @@ impl MachineState {
     pub fn read_term(&mut self, stream: Stream, indices: &mut IndexStore) -> CallResult {
         fn push_var_eq_functors<'a>(
             heap: &mut Heap,
-            iter: impl Iterator<Item = (&'a Var, &'a HeapCellValue)>,
+            iter: impl Iterator<Item = (&'a VarPtr, &'a HeapCellValue)>,
             atom_tbl: &mut AtomTable,
         ) -> Vec<HeapCellValue> {
             let mut list_of_var_eqs = vec![];
 
             for (var, binding) in iter {
-                let var_atom = atom_tbl.build_with(&var.to_string());
+                let var_atom = atom_tbl.build_with(&var.borrow().to_string());
                 let h = heap.len();
 
                 heap.push(atom_as_cell!(atom!("="), 2));
@@ -672,7 +672,7 @@ impl MachineState {
 
         let printer = match self.try_from_list(self.registers[6], stub_gen) {
             Ok(addrs) => {
-                let mut var_names: IndexMap<HeapCellValue, Var> = IndexMap::new();
+                let mut var_names: IndexMap<HeapCellValue, VarPtr> = IndexMap::new();
 
                 for addr in addrs {
                     read_heap_cell!(addr,
@@ -690,18 +690,18 @@ impl MachineState {
 
                                 read_heap_cell!(atom,
                                     (HeapCellValueTag::Char, c) => {
-                                        var_names.insert(var, Var::from(c.to_string()));
+                                        var_names.insert(var, VarPtr::from(c.to_string()));
                                     }
                                     (HeapCellValueTag::Atom, (name, _arity)) => {
                                         debug_assert_eq!(_arity, 0);
-                                        var_names.insert(var, Var::from(name.as_str()));
+                                        var_names.insert(var, VarPtr::from(name.as_str()));
                                     }
                                     (HeapCellValueTag::Str, s) => {
                                         let (name, arity) = cell_as_atom_cell!(self.heap[s])
                                             .get_name_and_arity();
 
                                         debug_assert_eq!(arity, 0);
-                                        var_names.insert(var, Var::from(name.as_str()));
+                                        var_names.insert(var, VarPtr::from(name.as_str()));
                                     }
                                     _ => {
                                         unreachable!();
index dab4c54cf7afa04c5eae9ba57252f31be8e4ca59..ddf64d34210078bd2f2210a688689817afc4da06 100644 (file)
@@ -68,7 +68,7 @@ pub struct Machine {
     pub(super) user_error: Stream,
     pub(super) load_contexts: Vec<LoadContext>,
     pub(super) runtime: Runtime,
-    pub(super) foreign_function_table: ForeignFunctionTable, 
+    pub(super) foreign_function_table: ForeignFunctionTable,
 }
 
 #[derive(Debug)]
@@ -365,46 +365,46 @@ impl Machine {
             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)
+            Instruction::ExecuteTermGreaterThan,
+            Instruction::ExecuteTermLessThan,
+            Instruction::ExecuteTermGreaterThanOrEqual,
+            Instruction::ExecuteTermLessThanOrEqual,
+            Instruction::ExecuteTermEqual,
+            Instruction::ExecuteTermNotEqual,
+            Instruction::ExecuteNumberGreaterThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
+            Instruction::ExecuteNumberLessThan(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
+            Instruction::ExecuteNumberGreaterThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
+            Instruction::ExecuteNumberLessThanOrEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
+            Instruction::ExecuteNumberEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
+            Instruction::ExecuteNumberNotEqual(ar_reg!(temp_v!(1)), ar_reg!(temp_v!(2))),
+            Instruction::ExecuteIs(temp_v!(1), ar_reg!(temp_v!(2))),
+            Instruction::ExecuteAcyclicTerm,
+            Instruction::ExecuteArg,
+            Instruction::ExecuteCompare,
+            Instruction::ExecuteCopyTerm,
+            Instruction::ExecuteFunctor,
+            Instruction::ExecuteGround,
+            Instruction::ExecuteKeySort,
+            Instruction::ExecuteRead,
+            Instruction::ExecuteSort,
+            Instruction::ExecuteN(1),
+            Instruction::ExecuteN(2),
+            Instruction::ExecuteN(3),
+            Instruction::ExecuteN(4),
+            Instruction::ExecuteN(5),
+            Instruction::ExecuteN(6),
+            Instruction::ExecuteN(7),
+            Instruction::ExecuteN(8),
+            Instruction::ExecuteN(9),
+            Instruction::ExecuteIsAtom(temp_v!(1)),
+            Instruction::ExecuteIsAtomic(temp_v!(1)),
+            Instruction::ExecuteIsCompound(temp_v!(1)),
+            Instruction::ExecuteIsInteger(temp_v!(1)),
+            Instruction::ExecuteIsNumber(temp_v!(1)),
+            Instruction::ExecuteIsRational(temp_v!(1)),
+            Instruction::ExecuteIsFloat(temp_v!(1)),
+            Instruction::ExecuteIsNonVar(temp_v!(1)),
+            Instruction::ExecuteIsVar(temp_v!(1))
         ].into_iter());
 
         for (p, instr) in self.code[impls_offset ..].iter().enumerate() {
@@ -690,6 +690,8 @@ impl Machine {
     fn try_call(&mut self, name: Atom, arity: usize, idx: IndexPtr) -> CallResult {
         let compiled_tl_index = idx.p() as usize;
 
+        // println!("calling {}/{}", name.as_str(), arity);
+
         match idx.tag() {
             IndexPtrTag::DynamicUndefined => {
                 self.machine_st.fail = true;
@@ -713,6 +715,8 @@ impl Machine {
     fn try_execute(&mut self, name: Atom, arity: usize, idx: IndexPtr) -> CallResult {
         let compiled_tl_index = idx.p() as usize;
 
+        // println!("executing {}/{}", name.as_str(), arity);
+
         match idx.tag() {
             IndexPtrTag::DynamicUndefined => {
                 self.machine_st.fail = true;
index 02e0e29fa413939c00e2dcc099e0aecaed407a54..a0cab8695830b77d01eb78e974dfd3b60f18303f 100644 (file)
@@ -10,20 +10,8 @@ use crate::parser::ast::*;
 use indexmap::IndexSet;
 
 use std::cell::Cell;
-use std::collections::VecDeque;
 use std::convert::TryFrom;
 
-pub(crate) fn fold_by_str<I>(terms: I, mut term: Term, sym: Atom) -> Term
-where
-    I: DoubleEndedIterator<Item = Term>,
-{
-    for prec in terms.rev() {
-        term = Term::Clause(Cell::default(), sym, vec![prec, term]);
-    }
-
-    term
-}
-
 pub(crate) fn to_op_decl(
     prec: u16,
     spec: Atom,
@@ -546,16 +534,15 @@ impl Preprocessor {
         }
     }
 
-    fn setup_fact(&mut self, term: Term) -> Result<Fact, CompilationError> {
+    fn setup_fact(&mut self, term: Term) -> Result<(Fact, VarData), CompilationError> {
         match term {
             Term::Clause(..) | Term::Literal(_, Literal::Atom(..)) => {
-                let mut classifier = VariableClassifier::new(
+                let classifier = VariableClassifier::new(
                     self.settings.default_call_policy(),
                 );
 
                 let (head, var_data) = classifier.classify_fact(term)?;
-
-                Ok(Fact { head, var_data })
+                Ok((Fact { head }, var_data))
             }
             _ => Err(CompilationError::InadmissibleFact),
         }
@@ -566,28 +553,22 @@ impl Preprocessor {
         loader: &mut Loader<'a, LS>,
         head: Term,
         body: Term,
-    ) -> Result<Rule, CompilationError> {
-        let mut classifier = VariableClassifier::new(
+    ) -> Result<(Rule, VarData), CompilationError> {
+        let classifier = VariableClassifier::new(
             self.settings.default_call_policy(),
         );
 
-        let (head, mut query_terms, var_data) =
-            classifier.classify_rule(loader, head, body)?;
-
-        let clauses = query_terms.drain(1..).collect();
-        let qt = query_terms.pop().unwrap();
+        let (head, clauses, var_data) = classifier.classify_rule(loader, head, body)?;
 
         match head {
-            Term::Clause(_, name, terms) => Ok(Rule {
-                head: (name, terms, qt),
+            Term::Clause(_, name, terms) => Ok((Rule {
+                head: (name, terms),
                 clauses,
-                var_data,
-            }),
-            Term::Literal(_, Literal::Atom(name)) => Ok(Rule {
-                head: (name, vec![], qt),
+            }, var_data)),
+            Term::Literal(_, Literal::Atom(name)) => Ok((Rule {
+                head: (name, vec![]),
                 clauses,
-                var_data,
-            }),
+            }, var_data)),
             _ => Err(CompilationError::InvalidRuleHead),
         }
     }
@@ -613,20 +594,29 @@ impl Preprocessor {
         term: Term,
     ) -> Result<TopLevel, CompilationError> {
         match term {
-            Term::Clause(r, name, terms) => {
+            Term::Clause(r, name, mut terms) => {
                 let is_rule = name == atom!(":-") && terms.len() == 2;
 
                 if is_rule {
-                    Ok(TopLevel::Rule(self.setup_rule(loader, terms[0], terms[1])?))
+                    let tail = terms.pop().unwrap();
+                    let head = terms.pop().unwrap();
+
+                    let (rule, var_data) = self.setup_rule(loader, head, tail)?;
+                    Ok(TopLevel::Rule(rule, var_data))
                 } else {
                     let term = Term::Clause(r, name, terms);
-                    Ok(TopLevel::Fact(self.setup_fact(term)?))
+                    let (fact, var_data) = self.setup_fact(term)?;
+                    Ok(TopLevel::Fact(fact, var_data))
                 }
             }
-            term => Ok(TopLevel::Fact(self.setup_fact(term)?)),
+            term => {
+                let (fact, var_data) = self.setup_fact(term)?;
+                Ok(TopLevel::Fact(fact, var_data))
+            }
         }
     }
 
+    /*
     fn try_terms_to_tls<'a, I: IntoIterator<Item = Term>, LS: LoadState<'a>>(
         &mut self,
         loader: &mut Loader<'a, LS>,
@@ -640,4 +630,5 @@ impl Preprocessor {
 
         Ok(results)
     }
+    */
 }
index d26468daa9341980a9d3d007964fdf18d3255334..7985f5fead390a9def50526b9d12ff1e48f76f8d 100644 (file)
@@ -1409,7 +1409,7 @@ impl Machine {
 
             let vars: Vec<_> = vars
                 .union(&result.supp_vars) // difference + union does not cancel.
-                .map(|v| Term::Var(Cell::default(), Var::Generated(v.get_value())))
+                .map(|v| Term::Var(Cell::default(), VarPtr::from(format!("_{}", v.get_value()))))
                 .collect();
 
             let helper_clause_loc = self.code.len();
@@ -1571,8 +1571,8 @@ impl Machine {
     #[inline(always)]
     pub(crate) fn is_reset_cont_marker(&self, p: usize) -> bool {
         match &self.code[p] {
-            &Instruction::CallResetContinuationMarker(_) |
-            &Instruction::ExecuteResetContinuationMarker(_) => true,
+            &Instruction::CallResetContinuationMarker |
+            &Instruction::ExecuteResetContinuationMarker => true,
             _ => false
         }
     }
@@ -4911,9 +4911,7 @@ impl Machine {
 
         let p_functor = self.deref_register(2);
 
-        let p = to_local_code_ptr(&self.machine_st.heap, p_functor).unwrap();
-
-        let num_cells = *self.code[p].perm_vars_mut().unwrap();
+        let num_cells = self.machine_st.stack.index_and_frame(e).prelude.num_cells;
         let mut addrs = vec![];
 
         for idx in 1..num_cells + 1 {
index 85e2e08671488b4472c4c12a4545fdf9d7c718cc..c1f1552fdf90334a44593478705607ca0d6de624 100644 (file)
@@ -540,23 +540,7 @@ macro_rules! functor_term {
 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
+        ClauseType::Inlined(InlinedClauseType::CompareNumber($cmp)).to_instr()
     }};
 }
 
index 73c91c6a4070ce13d48cb64fad9bff1cc4f510ee..283a9dc09705a3f11a2498e3dcc8bfce7f34e163 100644 (file)
@@ -4,11 +4,11 @@ use crate::machine::machine_indices::*;
 use crate::parser::char_reader::*;
 use crate::types::HeapCellValueTag;
 
-use std::cell::Cell;
+use std::cell::{Cell, Ref, RefCell, RefMut};
 use std::fmt;
-use std::hash::Hash;
+use std::hash::{Hash, Hasher};
 use std::io::{Error as IOError};
-use std::ops::Neg;
+use std::ops::{Deref, Neg};
 use std::rc::Rc;
 use std::vec::Vec;
 
@@ -572,23 +572,89 @@ impl Literal {
     }
 }
 
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct VarPtr(Rc<RefCell<Var>>);
+
+impl Hash for VarPtr {
+    #[inline(always)]
+    fn hash<H: Hasher>(&self, hasher: &mut H) {
+        self.borrow().hash(hasher)
+    }
+}
+
+impl Deref for VarPtr {
+    type Target = RefCell<Var>;
+
+    #[inline(always)]
+    fn deref(&self) -> &Self::Target {
+        self.0.deref()
+    }
+}
+
+impl VarPtr {
+    #[inline(always)]
+    pub(crate) fn borrow(&self) -> Ref<'_, Var> {
+        self.0.borrow()
+    }
+
+    #[inline(always)]
+    pub(crate) fn borrow_mut(&self) -> RefMut<'_, Var> {
+        self.0.borrow_mut()
+    }
+
+    pub(crate) fn to_var_num(&self) -> Option<usize> {
+        match *self.borrow() {
+            Var::Generated(var_num) => Some(var_num),
+            _ => None,
+        }
+    }
+
+    pub(crate) fn set(&self, var: Var) {
+        let mut var_ref = self.borrow_mut();
+        *var_ref = var;
+    }
+}
+
+impl From<Var> for VarPtr {
+    #[inline(always)]
+    fn from(value: Var) -> VarPtr {
+        VarPtr(Rc::new(RefCell::new(value)))
+    }
+}
+
+impl From<String> for VarPtr {
+    #[inline(always)]
+    fn from(value: String) -> VarPtr {
+        VarPtr::from(Var::from(value))
+    }
+}
+
+impl From<&str> for VarPtr {
+    #[inline(always)]
+    fn from(value: &str) -> VarPtr {
+        VarPtr::from(value.to_owned())
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum Var {
     Generated(usize),
-    Named(Rc<String>),
+    InSitu(usize),
+    Named(String),
 }
 
 impl From<String> for Var {
     #[inline(always)]
     fn from(value: String) -> Var {
-        Var::Named(Rc::new(value))
+        Var::Named(value)
     }
 }
 
 impl From<&str> for Var {
     #[inline(always)]
     fn from(value: &str) -> Var {
-        Var::Named(Rc::new(value.to_owned()))
+        Var::Named(value.to_owned())
     }
 }
 
@@ -596,16 +662,16 @@ impl Var {
     #[inline(always)]
     pub fn as_str(&self) -> Option<&str> {
         match self {
-            Var::Generated(_) => None,
             Var::Named(value) => Some(&value),
+            _ => None,
         }
     }
 
     #[inline(always)]
     pub fn to_string(&self) -> String {
         match self {
-            Var::Generated(n) => format!("_{}", n),
-            Var::Named(value) => value.to_string(),
+            Var::InSitu(n) | Var::Generated(n) => format!("_{}", n),
+            Var::Named(value) => value.to_owned(),
         }
     }
 }
@@ -620,7 +686,7 @@ pub enum Term {
     // other PartialString variants in as_partial_string.
     PartialString(Cell<RegType>, String, Box<Term>),
     CompleteString(Cell<RegType>, Atom),
-    Var(Cell<VarReg>, Var),
+    Var(Cell<VarReg>, VarPtr),
 }
 
 impl Term {
index ce633b9448a52208cb2cce2daef486572e5fd77f..021147eab47a127ee2801f6d84f8b7ce65fa9081 100644 (file)
@@ -426,7 +426,7 @@ impl<'a, R: CharRead> Parser<'a, R> {
                 if v.trim() == "_" {
                     self.terms.push(Term::AnonVar);
                 } else {
-                    self.terms.push(Term::Var(Cell::default(), Var::from(v)));
+                    self.terms.push(Term::Var(Cell::default(), VarPtr::from(v)));
                 }
 
                 TokenType::Term
index c8743c2f35ee89568747468a3b4aea9f0701917b..8f70eeecbe18dda7462a2d80087cade6d4555c67 100644 (file)
@@ -317,7 +317,7 @@ impl<'a, 'b> TermWriter<'a, 'b> {
     fn write_term_to_heap(mut self, term: &'a Term) -> Result<TermWriteResult, CompilationError> {
         let heap_loc = self.heap.len();
 
-        for term in breadth_first_iter(term, true) {
+        for term in breadth_first_iter(term, RootIterationPolicy::Iterated) {
             let h = self.heap.len();
 
             match &term {
@@ -372,9 +372,9 @@ impl<'a, 'b> TermWriter<'a, 'b> {
                     let addr = self.term_as_addr(&term, h);
                     self.heap.push(addr);
                 }
-                &TermRef::Var(Level::Root, _, ref var) => {
+                &TermRef::Var(Level::Root, _, ref var_ptr) => {
                     let addr = self.term_as_addr(&term, h);
-                    self.var_dict.insert(var.clone(), heap_loc_as_cell!(h));
+                    self.var_dict.insert(var_ptr.clone(), heap_loc_as_cell!(h));
                     self.heap.push(addr);
                 }
                 &TermRef::AnonVar(_) => {
index cbb469f9d26446890283c0fd9775e841988d9bd9..56a4c12754f339f08a11a5159838f0502c4a6179 100644 (file)
@@ -29,11 +29,13 @@ pub(crate) trait CompilationTarget<'a> {
 
     fn argument_to_variable(r: RegType, r: usize) -> Instruction;
     fn argument_to_value(r: RegType, val: usize) -> Instruction;
+    fn unsafe_argument_to_value(r: RegType, val: usize) -> Instruction;
 
     fn move_to_register(r: RegType, val: usize) -> Instruction;
 
     fn subterm_to_variable(r: RegType) -> Instruction;
     fn subterm_to_value(r: RegType) -> Instruction;
+    fn unsafe_subterm_to_value(r: RegType) -> Instruction;
 
     fn clause_arg_to_instr(r: RegType) -> Instruction;
 }
@@ -42,7 +44,7 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
     type Iterator = FactIterator<'a>;
 
     fn iter(term: &'a Term) -> Self::Iterator {
-        breadth_first_iter(term, false) // do not iterate over the root clause if one exists.
+        breadth_first_iter(term, RootIterationPolicy::NotIterated)
     }
 
     fn to_constant(lvl: Level, constant: Literal, reg: RegType) -> Instruction {
@@ -95,6 +97,10 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
         Instruction::GetValue(arg, val)
     }
 
+    fn unsafe_argument_to_value(arg: RegType, val: usize) -> Instruction {
+        Instruction::GetValue(arg, val)
+    }
+
     fn subterm_to_variable(val: RegType) -> Instruction {
         Instruction::UnifyVariable(val)
     }
@@ -103,6 +109,10 @@ impl<'a> CompilationTarget<'a> for FactInstruction {
         Instruction::UnifyValue(val)
     }
 
+    fn unsafe_subterm_to_value(val: RegType) -> Instruction {
+        Instruction::UnifyLocalValue(val)
+    }
+
     fn clause_arg_to_instr(val: RegType) -> Instruction {
         Instruction::UnifyVariable(val)
     }
@@ -165,6 +175,13 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
         Instruction::PutValue(arg, val)
     }
 
+    fn unsafe_argument_to_value(arg: RegType, val: usize) -> Instruction {
+        match arg {
+            RegType::Perm(p) => Instruction::PutUnsafeValue(p, val),
+            RegType::Temp(_) => Instruction::PutValue(arg, val),
+        }
+    }
+
     fn subterm_to_variable(val: RegType) -> Instruction {
         Instruction::SetVariable(val)
     }
@@ -173,6 +190,10 @@ impl<'a> CompilationTarget<'a> for QueryInstruction {
         Instruction::SetValue(val)
     }
 
+    fn unsafe_subterm_to_value(val: RegType) -> Instruction {
+        Instruction::SetLocalValue(val)
+    }
+
     fn clause_arg_to_instr(val: RegType) -> Instruction {
         Instruction::SetValue(val)
     }