streamline assertz/1, asserta/1

This commit is contained in:
Mark Thom
2022-07-19 20:29:22 -06:00
parent 1ffbf63d20
commit 6b05ee5130
6 changed files with 178 additions and 120 deletions

View File

@@ -190,9 +190,9 @@ enum REPLCodePtr {
DynamicProperty,
#[strum_discriminants(strum(props(Arity = "3", Name = "$abolish_clause")))]
AbolishClause,
#[strum_discriminants(strum(props(Arity = "5", Name = "$asserta")))]
#[strum_discriminants(strum(props(Arity = "3", Name = "$asserta")))]
Asserta,
#[strum_discriminants(strum(props(Arity = "5", Name = "$assertz")))]
#[strum_discriminants(strum(props(Arity = "3", Name = "$assertz")))]
Assertz,
#[strum_discriminants(strum(props(Arity = "4", Name = "$retract_clause")))]
Retract,
@@ -2195,6 +2195,7 @@ pub fn generate_instructions_rs() -> TokenStream {
let mut clause_type_from_name_and_arity_arms = vec![];
let mut clause_type_to_instr_arms = vec![];
let mut clause_type_name_arms = vec![];
let mut is_inbuilt_arms = vec![];
for (name, arity, variant) in instr_data.compare_number_variants {
let ident = variant.ident.clone();
@@ -2249,6 +2250,12 @@ pub fn generate_instructions_rs() -> TokenStream {
) => Instruction::#instr_ident(#(#placeholder_ids),*, 0)
}
);
is_inbuilt_arms.push(
quote! {
(atom!(#name), #arity) => true
}
);
}
for (name, arity, variant) in instr_data.compare_term_variants {
@@ -2278,6 +2285,12 @@ pub fn generate_instructions_rs() -> TokenStream {
) => Instruction::#instr_ident(0)
}
);
is_inbuilt_arms.push(
quote! {
(atom!(#name), #arity) => true
}
);
}
for (name, arity, variant) in instr_data.builtin_type_variants {
@@ -2339,6 +2352,12 @@ pub fn generate_instructions_rs() -> TokenStream {
) => Instruction::#instr_ident(0)
}
});
is_inbuilt_arms.push(
quote! {
(atom!(#name), #arity) => true
}
);
}
for (name, arity, variant) in instr_data.inlined_type_variants {
@@ -2398,6 +2417,12 @@ pub fn generate_instructions_rs() -> TokenStream {
) => Instruction::#instr_ident(#(#placeholder_ids),*,0)
}
);
is_inbuilt_arms.push(
quote! {
(atom!(#name), #arity) => true
}
);
}
for (name, arity, variant) in instr_data.system_clause_type_variants {
@@ -2488,6 +2513,18 @@ pub fn generate_instructions_rs() -> TokenStream {
) => Instruction::#instr_ident(0)
}
});
is_inbuilt_arms.push(
if let Arity::Ident("arity") = &arity {
quote! {
(atom!(#name), _arity) => true
}
} else {
quote! {
(atom!(#name), #arity) => true
}
}
);
}
for (name, arity, variant) in instr_data.repl_code_ptr_variants {
@@ -2553,6 +2590,12 @@ pub fn generate_instructions_rs() -> TokenStream {
)) => Instruction::#instr_ident(0)
}
});
is_inbuilt_arms.push(
quote! {
(atom!(#name), #arity) => true
}
);
}
for (name, arity, variant) in instr_data.clause_type_variants {
@@ -2622,6 +2665,12 @@ pub fn generate_instructions_rs() -> TokenStream {
ClauseType::#ident => Instruction::#ident(0)
}
});
is_inbuilt_arms.push(
quote! {
(atom!(#name), _arity) => true
}
);
}
let to_execute_arms: Vec<_> = instr_data.instr_variants
@@ -2972,19 +3021,12 @@ pub fn generate_instructions_rs() -> TokenStream {
}
}
pub fn is_builtin(&self) -> bool {
if let ClauseType::BuiltIn(_) = self {
true
} else {
false
}
}
pub fn is_inlined(&self) -> bool {
if let ClauseType::Inlined(_) = self {
true
} else {
false
pub fn is_inbuilt(name: Atom, arity: usize) -> bool {
match (name, arity) {
#(
#is_inbuilt_arms,
)*
_ => false,
}
}
@@ -3179,7 +3221,7 @@ enum Arity {
impl From<&'static str> for Arity {
fn from(arity: &'static str) -> Self {
usize::from_str_radix(&arity, 10)
.map(|n| Arity::Static(n))
.map(Arity::Static)
.unwrap_or_else(|_| Arity::Ident(arity))
}
}

View File

@@ -884,76 +884,45 @@ clause(H, B) :-
).
call_asserta(Head, Body, Name, Arity, Module) :-
'$clause_body_is_valid'(Body),
functor(_, Name, Arity),
'$asserta'(Head, Body, Name, Arity, Module).
module_asserta_clause(Head, Body, Module) :-
( var(Head) ->
throw(error(instantiation_error, asserta/1))
; callable(Head), functor(Head, Name, Arity) ->
( '$head_is_dynamic'(Module, Head) ->
call_asserta(Head, Body, Name, Arity, Module)
; '$no_such_predicate'(Module, Head) ->
call_asserta(Head, Body, Name, Arity, Module)
; throw(error(permission_error(modify, static_procedure, Name/Arity), asserta/1))
)
; throw(error(type_error(callable, Head), asserta/1))
).
:- meta_predicate asserta(:).
asserta(Clause0) :-
loader:strip_module(Clause0, Module, Clause),
( var(Module) -> Module = user
; true
),
( Clause \= (_ :- _) ->
Head = Clause,
Body = true,
module_asserta_clause(Head, Body, Module)
; Clause = (Head :- Body) ->
module_asserta_clause(Head, Body, Module)
).
loader:strip_subst_module(Clause0, user, Module, Clause),
asserta(Module, Clause).
module_assertz_clause(Head, Body, Module) :-
( var(Head) ->
throw(error(instantiation_error, assertz/1))
; callable(Head), functor(Head, Name, Arity) ->
( '$head_is_dynamic'(Module, Head) ->
call_assertz(Head, Body, Name, Arity, Module)
; '$no_such_predicate'(Module, Head) ->
call_assertz(Head, Body, Name, Arity, Module)
; throw(error(permission_error(modify, static_procedure, Name/Arity),
assertz/1))
)
; throw(error(type_error(callable, Head), assertz/1))
).
call_assertz(Head, Body, Name, Arity, Module) :-
'$clause_body_is_valid'(Body),
functor(_, Name, Arity),
'$assertz'(Head, Body, Name, Arity, Module).
asserta(Module, (Head :- Body)) :-
!,
'$asserta'(Module, Head, Body).
asserta(Module, Fact) :-
'$asserta'(Module, Fact, true).
:- meta_predicate assertz(:).
assertz(Clause0) :-
loader:strip_module(Clause0, Module, Clause),
( var(Module) -> Module = user
; true
),
( Clause \= (_ :- _) ->
Head = Clause,
Body = true,
module_assertz_clause(Head, Body, Module)
; Clause = (Head :- Body) ->
module_assertz_clause(Head, Body, Module)
).
loader:strip_subst_module(Clause0, user, Module, Clause),
assertz(Module, Clause).
assertz(Module, (Head :- Body)) :-
!,
'$assertz'(Module, Head, Body).
assertz(Module, Fact) :-
'$assertz'(Module, Fact, true).
:- meta_predicate retract(:).
retract(Clause0) :-
loader:strip_module(Clause0, Module, Clause),
( Clause \= (_ :- _) ->
loader:strip_module(Clause, Module, Head),
( var(Module) -> Module = user
; true
),
Body = true,
retract_module_clause(Head, Body, Module)
; Clause = (Head :- Body) ->
retract_module_clause(Head, Body, Module)
).
module_retract_clauses([Clause|Clauses0], Head, Body, Name, Arity, Module) :-
functor(VarHead, Name, Arity),
@@ -1040,22 +1009,6 @@ retract_clause(Head, Body) :-
).
:- meta_predicate retract(:).
retract(Clause0) :-
loader:strip_module(Clause0, Module, Clause),
( Clause \= (_ :- _) ->
loader:strip_module(Clause, Module, Head),
( var(Module) -> Module = user
; true
),
Body = true,
retract_module_clause(Head, Body, Module)
; Clause = (Head :- Body) ->
retract_module_clause(Head, Body, Module)
).
:- meta_predicate retractall(:).
retractall(Head) :-

View File

@@ -1899,13 +1899,10 @@ impl Machine {
}
}
pub(crate) fn compile_assert<'a>(&'a mut self, append_or_prepend: AppendOrPrepend) -> CallResult {
let key = self
.machine_st
.read_predicate_key(self.machine_st[temp_v!(3)], self.machine_st[temp_v!(4)]);
pub(crate) fn compile_assert(&mut self, append_or_prepend: AppendOrPrepend) -> CallResult
{
let module_name = cell_as_atom!(
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[5]))
self.machine_st.store(self.machine_st.deref(self.machine_st.registers[1]))
);
let compilation_target = match module_name {
@@ -1913,14 +1910,62 @@ impl Machine {
_ => CompilationTarget::Module(module_name),
};
let stub_gen = || {
match append_or_prepend {
AppendOrPrepend::Append => functor_stub(atom!("assertz"), 1),
AppendOrPrepend::Prepend => functor_stub(atom!("asserta"), 1),
}
};
let mut compile_assert = || {
let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> =
Loader::new(self, LiveTermStream::new(ListingSource::User));
loader.payload.compilation_target = compilation_target;
let head = loader.read_term_from_heap(temp_v!(1))?;
let body = loader.read_term_from_heap(temp_v!(2))?;
let head = loader.read_term_from_heap(temp_v!(2))?;
let name = if let Some(name) = head.name() {
name
} else {
return Err(SessionError::from(CompilationError::InvalidRuleHead));
};
let arity = head.arity();
let is_dynamic_predicate = loader
.wam_prelude
.indices
.is_dynamic_predicate(
module_name,
(name, arity),
);
let no_such_predicate =
if !is_dynamic_predicate && !ClauseType::is_inbuilt(name, arity) {
let idx_tag = loader
.wam_prelude
.indices
.get_predicate_code_index(
name,
arity,
module_name,
)
.map(|code_idx| code_idx.get_tag())
.unwrap_or(IndexPtrTag::DynamicUndefined);
idx_tag == IndexPtrTag::DynamicUndefined ||
idx_tag == IndexPtrTag::Undefined
} else {
is_dynamic_predicate
};
if !no_such_predicate {
LiveLoadAndMachineState::machine_st(&mut loader.payload).fail = true;
return LiveLoadAndMachineState::evacuate(loader);
}
let body = loader.read_term_from_heap(temp_v!(3))?;
let asserted_clause = Term::Clause(
Cell::default(),
@@ -1929,10 +1974,10 @@ impl Machine {
);
// if a new predicate was just created, make it dynamic.
loader.add_dynamic_predicate(compilation_target, key.0, key.1)?;
loader.add_dynamic_predicate(compilation_target, name, arity)?;
loader.incremental_compile_clause(
key,
(name, arity),
asserted_clause,
compilation_target,
false,
@@ -1943,7 +1988,7 @@ impl Machine {
LiveLoadAndMachineState::machine_st(&mut loader.payload).global_clock += 1;
loader.compile_clause_clauses(
key,
(name, arity),
compilation_target,
std::iter::once((head, body)),
append_or_prepend,
@@ -1954,14 +1999,30 @@ impl Machine {
match compile_assert() {
Ok(_) => Ok(()),
Err(e) => {
let stub = match append_or_prepend {
AppendOrPrepend::Append => functor_stub(atom!("assertz"), 1),
AppendOrPrepend::Prepend => functor_stub(atom!("asserta"), 1),
};
let err = self.machine_st.session_error(e);
Err(SessionError::CompilationError(
CompilationError::InvalidRuleHead |
CompilationError::InadmissibleFact
)) => {
let err = self.machine_st.type_error(
ValidType::Callable,
self.machine_st.registers[2],
);
Err(self.machine_st.error_form(err, stub))
Err(self.machine_st.error_form(err, stub_gen()))
}
Err(SessionError::CompilationError(
CompilationError::InadmissibleQueryTerm
)) => {
let err = self.machine_st.type_error(
ValidType::Callable,
self.machine_st.registers[3],
);
Err(self.machine_st.error_form(err, stub_gen()))
}
Err(e) => {
let err = self.machine_st.session_error(e);
Err(self.machine_st.error_form(err, stub_gen()))
}
}
}

View File

@@ -639,10 +639,10 @@ impl CompilationError {
&CompilationError::ExpectedRel => {
functor!(atom!("expected_relation"))
}
&CompilationError::InadmissibleFact => {
&CompilationError::InadmissibleFact => { // TODO: type_error(callable, _).
functor!(atom!("inadmissible_fact"))
}
&CompilationError::InadmissibleQueryTerm => {
&CompilationError::InadmissibleQueryTerm => { // TODO: type_error(callable, _).
functor!(atom!("inadmissible_query_term"))
}
&CompilationError::InconsistentEntry => {
@@ -661,7 +661,8 @@ impl CompilationError {
functor!(atom!("no_such_module"), [atom(module_name)])
}
&CompilationError::InvalidRuleHead => {
functor!(atom!("invalid_head_of_rule"))
functor!(atom!("invalid_head_of_rule")) // TODO: type_error(callable, _).
}
&CompilationError::InvalidUseModuleDecl => {
functor!(atom!("invalid_use_module_declaration"))

View File

@@ -193,6 +193,11 @@ impl CodeIndex {
*self.0.deref_mut() = value;
}
#[inline(always)]
pub(crate) fn get_tag(self) -> IndexPtrTag {
self.0.tag()
}
#[inline(always)]
pub(crate) fn replace(&mut self, value: IndexPtr) -> IndexPtr {
std::mem::replace(self.0.deref_mut(), value)

View File

@@ -4326,9 +4326,7 @@ impl Machine {
let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
.get_name_and_arity();
let ct = ClauseType::from(name, arity, &mut self.machine_st.arena);
if ct.is_inlined() || ct.is_builtin() {
if ClauseType::is_inbuilt(name, arity) {
true
} else {
let index = self.indices.get_predicate_code_index(
@@ -4348,9 +4346,7 @@ impl Machine {
(HeapCellValueTag::Atom, (name, arity)) => {
debug_assert_eq!(arity, 0);
let ct = ClauseType::from(name, 0, &mut self.machine_st.arena);
if ct.is_inlined() || ct.is_builtin() {
if ClauseType::is_inbuilt(name, 0) {
true
} else {
let index = self.indices.get_predicate_code_index(