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,
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();
) => 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 {
) => Instruction::#instr_ident(0)
}
);
+
+ is_inbuilt_arms.push(
+ quote! {
+ (atom!(#name), #arity) => true
+ }
+ );
}
for (name, arity, variant) in instr_data.builtin_type_variants {
) => Instruction::#instr_ident(0)
}
});
+
+ is_inbuilt_arms.push(
+ quote! {
+ (atom!(#name), #arity) => true
+ }
+ );
}
for (name, arity, variant) in instr_data.inlined_type_variants {
) => 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 {
) => 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 {
)) => Instruction::#instr_ident(0)
}
});
+
+ is_inbuilt_arms.push(
+ quote! {
+ (atom!(#name), #arity) => true
+ }
+ );
}
for (name, arity, variant) in instr_data.clause_type_variants {
ClauseType::#ident => Instruction::#ident(0)
}
});
+
+ is_inbuilt_arms.push(
+ quote! {
+ (atom!(#name), _arity) => true
+ }
+ );
}
let to_execute_arms: Vec<_> = instr_data.instr_variants
}
}
- 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,
}
}
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))
}
}
).
-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).
+asserta(Module, (Head :- Body)) :-
+ !,
+ '$asserta'(Module, Head, Body).
+asserta(Module, Fact) :-
+ '$asserta'(Module, Fact, true).
-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))
- ).
+:- meta_predicate assertz(:).
+
+assertz(Clause0) :-
+ 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).
-call_assertz(Head, Body, Name, Arity, Module) :-
- '$clause_body_is_valid'(Body),
- functor(_, Name, Arity),
- '$assertz'(Head, Body, Name, Arity, Module).
-:- meta_predicate assertz(:).
+:- meta_predicate retract(:).
-assertz(Clause0) :-
+retract(Clause0) :-
loader:strip_module(Clause0, Module, Clause),
- ( var(Module) -> Module = user
- ; true
- ),
( Clause \= (_ :- _) ->
- Head = Clause,
+ loader:strip_module(Clause, Module, Head),
+ ( var(Module) -> Module = user
+ ; true
+ ),
Body = true,
- module_assertz_clause(Head, Body, Module)
+ retract_module_clause(Head, Body, Module)
; Clause = (Head :- Body) ->
- module_assertz_clause(Head, Body, Module)
+ retract_module_clause(Head, Body, Module)
).
-
module_retract_clauses([Clause|Clauses0], Head, Body, Name, Arity, Module) :-
functor(VarHead, Name, Arity),
findall((VarHead :- VarBody), Module:'$clause'(VarHead, VarBody), Clauses1),
).
-:- 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) :-
}
}
- 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 {
_ => 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(),
);
// 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,
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,
match compile_assert() {
Ok(_) => Ok(()),
+ 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_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 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(self.machine_st.error_form(err, stub))
+ Err(self.machine_st.error_form(err, stub_gen()))
}
}
}
&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 => {
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"))
*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)
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(
(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(