cleanup code generation, add throw/catch, copy_term, var, atomic, not, false builtins
This commit is contained in:
125
src/prolog/builtins.rs
Normal file
125
src/prolog/builtins.rs
Normal file
@@ -0,0 +1,125 @@
|
||||
use prolog::ast::*;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub type PredicateKey = (Atom, usize); // name, arity, type.
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum PredicateKeyType {
|
||||
BuiltIn,
|
||||
User
|
||||
}
|
||||
|
||||
pub type CodeDir = HashMap<PredicateKey, (PredicateKeyType, usize)>;
|
||||
|
||||
fn get_builtins() -> Code {
|
||||
vec![internal_call_n!(), // callN/N, 0.
|
||||
is_atomic!(), // atomic/1, 1.
|
||||
proceed!(),
|
||||
is_var!(), // var/1, 3.
|
||||
proceed!(),
|
||||
allocate!(4), // catch/3, 5.
|
||||
query![get_var_in_query!(perm_v!(2), 1),
|
||||
get_var_in_query!(perm_v!(3), 2),
|
||||
get_var_in_query!(perm_v!(1), 3),
|
||||
put_var!(perm_v!(4), 1)],
|
||||
get_current_block!(),
|
||||
query![put_value!(perm_v!(2), 1),
|
||||
put_value!(perm_v!(3), 2),
|
||||
put_value!(perm_v!(1), 3),
|
||||
put_unsafe_value!(4, 4)],
|
||||
deallocate!(),
|
||||
goto!(11, 4),
|
||||
try_me_else!(9), // catch/4, 11.
|
||||
allocate!(3),
|
||||
query![get_var_in_query!(perm_v!(3), 1),
|
||||
get_var_in_query!(perm_v!(2), 4),
|
||||
put_var!(perm_v!(1), 1)],
|
||||
install_new_block!(),
|
||||
query![put_value!(perm_v!(3), 1)],
|
||||
call_n!(1),
|
||||
query![put_value!(perm_v!(2), 1),
|
||||
put_unsafe_value!(1, 2)],
|
||||
deallocate!(),
|
||||
goto!(42, 2), // goto end_block/2 at 42.
|
||||
trust_me!(),
|
||||
allocate!(4),
|
||||
query![get_var_in_query!(perm_v!(2), 2),
|
||||
get_var_in_query!(perm_v!(1), 3),
|
||||
get_var_in_query!(temp_v!(2), 1),
|
||||
put_value!(temp_v!(4), 1)],
|
||||
reset_block!(),
|
||||
query![put_var!(perm_v!(4), 1)],
|
||||
get_ball!(),
|
||||
query![put_value!(perm_v!(4), 1),
|
||||
put_var!(perm_v!(3), 2)],
|
||||
copy_term!(),
|
||||
query![put_unsafe_value!(3, 1),
|
||||
put_value!(perm_v!(2), 2),
|
||||
put_value!(perm_v!(1), 3)],
|
||||
deallocate!(),
|
||||
goto!(31, 2), // goto handle_ball/2.
|
||||
try_me_else!(10), // handle_ball/2, 31.
|
||||
allocate!(2),
|
||||
get_level!(),
|
||||
query![get_var_in_query!(perm_v!(2), 3)],
|
||||
unify!(),
|
||||
cut!(non_terminal!()),
|
||||
query![put_value!(perm_v!(2), 1)],
|
||||
deallocate!(),
|
||||
execute_n!(1),
|
||||
trust_me!(),
|
||||
unwind_stack!(),
|
||||
try_me_else!(8), // end_block/2, 42.
|
||||
allocate!(1),
|
||||
query![get_var_in_query!(perm_v!(1), 1),
|
||||
put_value!(temp_v!(2), 1)],
|
||||
clean_up_block!(),
|
||||
query![put_value!(perm_v!(1), 1)],
|
||||
deallocate!(),
|
||||
reset_block!(),
|
||||
proceed!(),
|
||||
trust_me!(),
|
||||
allocate!(0),
|
||||
query![get_var_in_query!(temp_v!(3), 1),
|
||||
put_value!(temp_v!(2), 1)],
|
||||
reset_block!(),
|
||||
deallocate!(),
|
||||
goto!(58, 0), // goto false.
|
||||
set_ball!(), // throw/1, 56.
|
||||
unwind_stack!(),
|
||||
fail!(), // false/0, 58.
|
||||
proceed!(),
|
||||
try_me_else!(7), // not/1, 60.
|
||||
allocate!(1),
|
||||
get_level!(),
|
||||
call_n!(1),
|
||||
cut!(non_terminal!()),
|
||||
deallocate!(),
|
||||
goto!(58, 0), // goto false.
|
||||
trust_me!(),
|
||||
proceed!(),
|
||||
copy_term!(), // copy_term/2, 69.
|
||||
proceed!()]
|
||||
}
|
||||
|
||||
pub fn build_code_dir() -> (Code, CodeDir) {
|
||||
let mut code_dir = HashMap::new();
|
||||
let builtin_code = get_builtins();
|
||||
|
||||
// there are 63 registers in the VM, so call/N is defined for all 0 <= N <= 62
|
||||
// (an extra register is needed for the predicate name)
|
||||
for arity in 0 .. 63 {
|
||||
code_dir.insert((String::from("call"), arity), (PredicateKeyType::BuiltIn, 0));
|
||||
}
|
||||
|
||||
code_dir.insert((String::from("atomic"), 1), (PredicateKeyType::BuiltIn, 1));
|
||||
code_dir.insert((String::from("var"), 1), (PredicateKeyType::BuiltIn, 3));
|
||||
code_dir.insert((String::from("false"), 0), (PredicateKeyType::BuiltIn, 58));
|
||||
code_dir.insert((String::from("not"), 1), (PredicateKeyType::BuiltIn, 60));
|
||||
code_dir.insert((String::from("copy_term"), 2), (PredicateKeyType::BuiltIn, 69));
|
||||
code_dir.insert((String::from("catch"), 3), (PredicateKeyType::BuiltIn, 5));
|
||||
code_dir.insert((String::from("throw"), 1), (PredicateKeyType::BuiltIn, 56));
|
||||
|
||||
(builtin_code, code_dir)
|
||||
}
|
||||
Reference in New Issue
Block a user