]> Repositorios git - scryer-prolog.git/commitdiff
refine is/2 compilation so errors are thrown when expected without needlessly allocat...
authorMark <[email protected]>
Tue, 29 Aug 2023 22:42:23 +0000 (16:42 -0600)
committerMark <[email protected]>
Tue, 29 Aug 2023 22:42:23 +0000 (16:42 -0600)
build/instructions_template.rs
src/codegen.rs
src/machine/dispatch.rs

index 3ac76eff89071432bc607e9480edd0dfcb9f681b..52fcd8b7a06567e5b106569b09f710f5be07c984 100644 (file)
@@ -99,6 +99,8 @@ enum BuiltInClauseType {
     Ground,
     #[strum_discriminants(strum(props(Arity = "2", Name = "is")))]
     Is(RegType, ArithmeticTerm),
+    #[strum_discriminants(strum(props(Arity = "1", Name = "$get_number")))]
+    GetNumber(ArithmeticTerm),
     #[strum_discriminants(strum(props(Arity = "2", Name = "keysort")))]
     KeySort,
     #[strum_discriminants(strum(props(Arity = "2", Name = "sort")))]
@@ -1553,7 +1555,8 @@ fn generate_instruction_preface() -> TokenStream {
                     &Instruction::CallFunctor |
                     &Instruction::CallGround |
                     &Instruction::CallKeySort |
-                    &Instruction::CallSort => {
+                    &Instruction::CallSort |
+                    &Instruction::CallGetNumber(_) => {
                         let (name, arity) = self.to_name_and_arity();
                         functor!(atom!("call"), [atom(name), fixnum(arity)])
                     }
@@ -1578,7 +1581,8 @@ fn generate_instruction_preface() -> TokenStream {
                     &Instruction::ExecuteGround |
                     &Instruction::ExecuteIs(..) |
                     &Instruction::ExecuteKeySort |
-                    &Instruction::ExecuteSort => {
+                    &Instruction::ExecuteSort |
+                    &Instruction::ExecuteGetNumber(_) => {
                         let (name, arity) = self.to_name_and_arity();
                         functor!(atom!("execute"), [atom(name), fixnum(arity)])
                     }
@@ -1603,7 +1607,8 @@ fn generate_instruction_preface() -> TokenStream {
                     &Instruction::DefaultCallGround |
                     &Instruction::DefaultCallIs(..) |
                     &Instruction::DefaultCallKeySort |
-                    &Instruction::DefaultCallSort => {
+                    &Instruction::DefaultCallSort |
+                    &Instruction::DefaultCallGetNumber(_) => {
                         let (name, arity) = self.to_name_and_arity();
                         functor!(atom!("call_default"), [atom(name), fixnum(arity)])
                     }
@@ -1628,7 +1633,8 @@ fn generate_instruction_preface() -> TokenStream {
                     &Instruction::DefaultExecuteGround |
                     &Instruction::DefaultExecuteIs(..) |
                     &Instruction::DefaultExecuteKeySort |
-                    &Instruction::DefaultExecuteSort => {
+                    &Instruction::DefaultExecuteSort |
+                    &Instruction::DefaultExecuteGetNumber(_) => {
                         let (name, arity) = self.to_name_and_arity();
                         functor!(atom!("execute_default"), [atom(name), fixnum(arity)])
                     }
index f69fa2a9ba8240b6e568883fe804e279df3bb60b..4902a61845222bb1da6e2a92a4661dfdd55f677f 100644 (file)
@@ -814,19 +814,34 @@ impl<'b> CodeGenerator<'b> {
                     );
 
                     self.marker.mark_safe_var_unconditionally(var_num);
+                    compile_expr!(self, &terms[1], term_loc, code)
                 } else {
-                    if self.marker.in_tail_position {
-                        if self.marker.var_data.allocates {
-                            code.push_back(instr!("deallocate"));
+                    if let Term::Var(ref vr, ref var) = &terms[1] {
+                        let var_num = var.to_var_num().unwrap();
+
+                        // if var is an anonymous variable, insert
+                        // is/2 call so that an instantiation error is
+                        // thrown when the predicate is run.
+                        if self.marker.var_data.records[var_num].num_occurrences > 1 {
+                            self.marker.mark_var::<QueryInstruction>(
+                                var_num,
+                                Level::Shallow,
+                                vr,
+                                term_loc,
+                                code,
+                            );
+
+                            self.marker.mark_safe_var_unconditionally(var_num);
+
+                            let at = ArithmeticTerm::Reg(vr.get().norm());
+                            self.add_call(code, instr!("$get_number", at), call_policy);
+
+                            return Ok(());
                         }
-
-                        code.push_back(instr!("proceed"));
                     }
 
-                    return Ok(());
+                    compile_expr!(self, &terms[1], term_loc, code)
                 }
-
-                compile_expr!(self, &terms[1], term_loc, code)
             }
             &Term::Literal(_, c @ Literal::Integer(_) |
                               c @ Literal::Float(_) |
index 8752522d8f7ef030cd09d78c0d7e260102badc7b..dc55ed86184dcfcf09387d759c4aa1a902519ae0 100644 (file)
@@ -1497,6 +1497,14 @@ impl Machine {
                     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::DefaultCallGetNumber(at) => {
+                    try_or_throw!(self.machine_st, self.machine_st.get_number(at));
+                    step_or_fail!(self, self.machine_st.p += 1);
+                }
+                Instruction::DefaultExecuteGetNumber(at) => {
+                    try_or_throw!(self.machine_st, self.machine_st.get_number(at));
+                    step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
+                }
                 &Instruction::CallAcyclicTerm => {
                     let addr = self.machine_st.registers[1];
 
@@ -1965,6 +1973,34 @@ impl Machine {
                         self.machine_st.p = self.machine_st.cp;
                     }
                 }
+                Instruction::CallGetNumber(at) => {
+                    try_or_throw!(self.machine_st, self.machine_st.get_number(at));
+
+                    if self.machine_st.fail {
+                        self.machine_st.backtrack();
+                    } else {
+                        try_or_throw!(
+                            self.machine_st,
+                            (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+                        );
+
+                        self.machine_st.p += 1;
+                    }
+                }
+                Instruction::ExecuteGetNumber(at) => {
+                    try_or_throw!(self.machine_st, self.machine_st.get_number(at));
+
+                    if self.machine_st.fail {
+                        self.machine_st.backtrack();
+                    } else {
+                        try_or_throw!(
+                            self.machine_st,
+                            (self.machine_st.increment_call_count_fn)(&mut self.machine_st)
+                        );
+
+                        self.machine_st.p = self.machine_st.cp;
+                    }
+                }
                 &Instruction::CallN(arity) => {
                     let pred = self.machine_st.registers[1];