Java "Store"

Admin User, erstellt 27. Apr. 2024
         
package nova;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Warranty & Liability
* To the extent permitted by applicable law and unless explicitly
* otherwise agreed upon, XLOG Technologies AG makes no warranties
* regarding the provided information. XLOG Technologies AG assumes
* no liability that any problems might be solved with the information
* provided by XLOG Technologies AG.
* <p/>
* Rights & License
* All industrial property rights regarding the information - copyright
* and patent rights in particular - are the sole property of XLOG
* Technologies AG. If the company was not the originator of some
* excerpts, XLOG Technologies AG has at least obtained the right to
* reproduce, change and translate the information.
* <p/>
* Reproduction is restricted to the whole unaltered document. Reproduction
* of the information is only allowed for non-commercial uses. Selling,
* giving away or letting of the execution of the library is prohibited.
* The library can be distributed as part of your applications and libraries
* for execution provided this comment remains unchanged.
* <p/>
* Restrictions
* Only to be distributed with programs that add significant and primary
* functionality to the library. Not to be distributed with additional
* software intended to replace any components of the library.
* <p/>
* Trademarks
* Jekejeke is a registered trademark of XLOG Technologies AG.
*/
public final class Store {
public static final int UNDEF_INT = -2;
public static final Object UNDEF_OBJ = new Object();
public static final int MASK_PRED_DYNAMIC = 0x00000001;
public static final int MASK_PRED_SPECIAL = 0x00000002;
public static final int MASK_PRED_CHECK = 0x00000004;
public static final int MASK_PRED_ARITHMETIC = 0x00000008;
public static final int MASK_TOUCH_DYNAMIC = 0x00000001;
public static final int MASK_ADD_BOTTOM = 0x00000001;
public static final int MASK_ADD_DYNAMIC = 0x00000002;
public static final int MASK_REMOVE_BOTTOM = 0x00000001;
public static HashMap<String, Handler.Rope<Provable>> kb = new HashMap<>();
public static int stage = -1;
/**
* Set the clause and predicate current stage.
*
* @param num The current stage.
*/
public static void set_stage(int num) {
stage = num;
}
/**
* Set the clause current partition.
*
* @param path The current partition.
*/
public static void set_partition(String path) {
engine.partition = path;
}
/**************************************************************/
/* Engine */
/**************************************************************/
public static final class Engine {
public Object signal;
public Runnable interrupt;
public Runtime.Sink text_output;
public Runtime.Sink text_error;
public Runtime.Source text_input;
public int low;
public int high;
public int serno;
public Variable backtrail;
public int backcount;
public String partition;
/**
* Create a slow state engine.
*/
Engine() {
this.signal = Store.UNDEF_OBJ;
this.interrupt = () -> {};
this.text_output = null;
this.text_error = null;
this.text_input = null;
this.low = 0;
this.high = 0;
this.serno = 0;
this.backtrail = null;
this.backcount = 0;
this.partition = (stage == -1 ? "system" : "user");
}
}
public static Engine engine = new Engine();
public static void set_engine(Engine ptr) {
engine = ptr;
}
/**************************************************************/
/* Variable & Compound */
/**************************************************************/
public static final class Variable {
public Object instantiated;
public int flags;
public Variable tail;
/**
* Create a Prolog variable.
*/
public Variable() {
this.instantiated = UNDEF_OBJ;
if (engine.low < engine.high) {
this.flags = engine.low;
engine.low++;
} else {
this.flags = engine.serno;
engine.serno++;
}
this.tail = null;
}
}
/**
* Check whether an object is a variable.
*
* @param obj The object.
* @return boolean True if the object is a variable, otherwise false.
*/
public static boolean is_variable(Object obj) {
return obj instanceof Variable;
}
public static final class Compound {
public Object functor;
public Object[] args;
/**
* Create a Prolog compound.
*
* @param functor The functor.
* @param args The arguments.
*/
public Compound(Object functor, Object[] args) {
this.functor = functor;
this.args = args;
}
}
/**
* Check whether an object is a compound.
*
* @param obj The object.
* @return boolean True if the object is a compound, otherwise false.
*/
public static boolean is_compound(Object obj) {
return obj instanceof Compound;
}
/**************************************************************/
/* Place & Skeleton */
/**************************************************************/
public static final class Place {
public int index;
/**
* Create a Albufeira Code place.
*/
public Place(int index) {
this.index = index;
}
}
/**
* Check whether an object is a place.
*
* @param obj The object.
* @return boolean True if the object is a place, otherwise false.
*/
public static boolean is_place(Object obj) {
return obj instanceof Place;
}
public static final class Skeleton {
public Object functor;
public Object[] args;
/**
* Create a Albufeira Code skeleton.
*
* @param functor The functor.
* @param args The arguments.
*/
public Skeleton(Object functor, Object[] args) {
this.functor = functor;
this.args = args;
}
}
/**
* Check whether an object is a skeleton.
*
* @param obj The object.
* @return boolean True if the object is a skeleton, otherwise false.
*/
public static boolean is_skeleton(Object obj) {
return obj instanceof Skeleton;
}
/**************************************************************/
/* Quote */
/**************************************************************/
public static final class Quote {
public Object obj;
/**
* Create a Albufeira Code quote.
*/
public Quote(Object obj) {
this.obj = obj;
}
}
/**
* Check whether an object is a quote.
*
* @param obj The object.
* @return boolean True if the object is a quote, otherwise false.
*/
public static boolean is_quote(Object obj) {
return obj instanceof Quote;
}
public static void unquote_objects(Object[] body) {
for (int i = 0; i < body.length; i++) {
Object alpha = body[i];
if (Store.is_quote(alpha))
body[i] = ((Quote) alpha).obj;
}
}
/**************************************************************/
/* Clauses Lifecycle */
/**************************************************************/
public static final class Clause {
public int size;
public Object[] head;
public Object[] body;
public int cutvar;
public Object idxval;
public int creator;
public int remover;
public String shard;
public Clause(int size, Object[] head, Object[] body, int cutvar, Object idxval) {
this.size = size;
this.head = head;
this.body = body;
this.cutvar = cutvar;
this.idxval = idxval;
this.creator = stage;
this.remover = Store.UNDEF_INT;
this.shard = "";
}
}
/**
* Check whether the object is a clause.
*
* @param obj The object.
* @return boolean if the object is a clause, otherwise false.
*/
public static boolean is_clause(Object obj) {
return obj instanceof Clause;
}
public static final class Logical {
public Clause[] cache;
public int count;
public Handler.Rope<Clause> data;
/**
* Create a logical.
*
* @param cache The cache of non-deleted clauses.
* @param count The counter of non-deleted clauses.
* @param data The clause list.
*/
Logical(Clause[] cache, int count, Handler.Rope<Clause> data) {
this.cache = cache;
this.count = count;
this.data = data;
}
}
/**
* Check whether an object is a logical.
*
* @param obj The object.
* @return boolean if the object is a logical, otherwise false.
*/
public static boolean is_logical(Object obj) {
return obj instanceof Logical;
}
/**************************************************************/
/* Knowledgebase */
/**************************************************************/
public static final class Provable {
public int flags;
public Logical rope;
public Logical nonguard;
public HashMap<Object, Logical> idxmap;
public Object func;
public int creator;
public int remover;
public Provable overlay;
/**
* Create a provable.
*
* @param flags The flags.
*/
Provable(int flags) {
this.flags = flags;
this.rope = null;
this.nonguard = null;
this.idxmap = null;
this.func = null;
this.creator = stage;
this.remover = Store.UNDEF_INT;
this.overlay = null;
}
}
/**
* Check whether an object is a provable.
*
* @param obj The object.
* @return boolean True if the object is a provable, otherwise false.
*/
public static boolean is_provable(Object obj) {
return obj instanceof Provable;
}
public static final class Cache {
public Provable link;
public String name;
/**
* Create a cache node.
*
* @param name The functor.
*/
public Cache(String name) {
this.link = null;
this.name = name;
}
}
/**
* Check whether an object is a cache.
*
* @param obj The object.
* @return boolean True if the object is a cache, otherwise false.
*/
public static boolean is_cache(Object obj) {
return obj instanceof Cache;
}
/******************************************************************/
/* Snapshot Data */
/******************************************************************/
/**
* Make snapshot of a logical.
*
* @param rope The logical.
* @return array The clause list snapshot.
*/
public static Clause[] snapshot_data(Logical rope) {
Clause[] res = rope.cache;
if (res == null) {
res = new Clause[rope.count];
rope_copy(res, rope);
rope.cache = res;
}
return res;
}
static void rope_copy(Clause[] res, Logical rope) {
Handler.Rope<Clause> data = rope.data;
int j = 0;
for (int i = 0; i < data.size(); i++) {
Clause clause = data.get(i);
if (clause.remover == Store.UNDEF_INT)
res[j++] = clause;
}
}
/******************************************************************/
/* Linked Provables */
/******************************************************************/
/**
* Retrieve a provable from monomorphic cache.
*
* @param cache The cache.
* @param arity The arity.
* @return The provable or null.
*/
public static Provable ensure_link(Cache cache, int arity) {
Provable peek = cache.link;
if (peek == null || peek.remover != Store.UNDEF_INT) {
peek = Store.pred_link(cache.name, arity);
cache.link = peek;
}
return peek;
}
/**
* Retrieve a provable by predicate indicator.
*
* @param functor The functor.
* @param arity The arity.
* @return The provable or null.
*/
public static Provable pred_link(String functor, int arity) {
Handler.Rope<Provable> temp = kb.get(functor);
if (temp == null)
return null;
Provable peek = (arity < temp.size() ? temp.get(arity) : null);
if (peek == null || peek.remover != Store.UNDEF_INT)
return null;
return peek;
}
/**
* The function returns an anonymous predicate for the given clauses.
*
* @param rope The clauses.
* @return Provable predicate.
*/
public static Provable make_defined(Object[] rope) {
Provable peek = new Provable(0);
peek.rope = new_rope();
peek.nonguard = new_rope();
peek.idxmap = new HashMap<>();
for (int i = 0; i < rope.length; i++)
add_peek(peek, (Clause) rope[i], MASK_ADD_BOTTOM);
return peek;
}
static Logical new_rope() {
return new Logical(null, 0, new Handler.Rope<>());
}
/**************************************************************/
/* Dynamic Predicates */
/**************************************************************/
/**
* Create a new dynamic predicate entry.
*
* @param functor The functor.
* @param arity The arity.
* @param flags The flags.
*/
public static void pred_touch(String functor, int arity, int flags) {
Handler.Rope<Provable> temp = kb.get(functor);
if (temp == null) {
temp = new Handler.Rope<>();
kb.put(functor, temp);
}
Provable peek = (arity < temp.size() ? temp.get(arity) : null);
if (peek == null || peek.remover != Store.UNDEF_INT) {
Provable res = make_defined(Machine.VOID_ARGS);
if (peek != null)
res.overlay = peek;
if ((flags & MASK_TOUCH_DYNAMIC) != 0)
res.flags |= MASK_PRED_DYNAMIC;
while (arity >= temp.size())
temp.add(null);
temp.set(arity, res);
} else {
if (!is_logical(peek.rope))
throw Machine.make_error(new Compound("permission_error",
new Object[]{"modify", "static_procedure",
Machine.make_indicator(functor, arity)}));
if ((flags & MASK_TOUCH_DYNAMIC) != 0)
if ((peek.flags & MASK_PRED_DYNAMIC) == 0)
throw Machine.make_error(new Compound("permission_error",
new Object[]{"modify", "static_procedure",
Machine.make_indicator(functor, arity)}));
}
}
/*********************************************************************/
/* Destroy Provable */
/*********************************************************************/
/**
* Remove a predicate from the knowledge base.
*
* @param functor The functor.
* @param arity The arity.
*/
public static void pred_destroy(String functor, int arity) {
Handler.Rope<Provable> temp = kb.get(functor);
if (temp == null)
return;
Provable peek = (arity < temp.size() ? temp.get(arity) : null);
if (peek == null || peek.remover != Store.UNDEF_INT)
return;
if (peek.creator == stage) {
peek = clear_pop(peek);
temp.set(arity, peek);
if (peek == null && trim_arities(temp))
kb.remove(functor);
} else {
peek.remover = stage;
}
}
/**
* Clear and pop a provable.
*
* @param peek The provable.
* @return The parent provable.
*/
private static Provable clear_pop(Provable peek) {
peek.remover = stage;
peek.rope = null;
peek.idxmap = null;
peek.nonguard = null;
Provable back = peek;
peek = back.overlay;
back.overlay = null;
return peek;
}
/**
* Trim the arities array.
*
* @param peek The arities array.
* @return boolean True if empty, otherwise fale.
*/
private static boolean trim_arities(Handler.Rope<Provable> peek) {
int pos = peek.size();
while (pos > 0 && peek.get(pos - 1) == null)
pos--;
if (pos == 0)
return true;
if (pos != peek.size())
peek.removeRange(pos, peek.size());
return false;
}
/**************************************************************/
/* Clauses Transactions */
/**************************************************************/
/**
* Rollback the clauses.
*/
public static void clear() {
Iterator<Map.Entry<String, Handler.Rope<Provable>>> it = kb.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, Handler.Rope<Provable>> entry = it.next();
Handler.Rope<Provable> temp = entry.getValue();
for (int i = 0; i < temp.size(); i++) {
Provable peek = temp.get(i);
if (peek == null)
continue;
if (peek.creator == stage) {
peek = clear_pop(peek);
temp.set(i, peek);
if (peek == null)
continue;
}
if (peek.remover == stage)
peek.remover = Store.UNDEF_INT;
if (is_logical(peek.rope))
rollback_peek(peek);
}
if (trim_arities(temp))
it.remove();
}
}
/**
* Rollback the clauses of a predicate.
*
* @param peek The predicate.
*/
static void rollback_peek(Provable peek) {
if (!has_action(peek.rope))
return;
Iterator<Map.Entry<Object, Logical>> it = peek.idxmap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Object, Logical> entry = it.next();
if (has_action(entry.getValue())) {
rollback_rope(entry.getValue(), false);
if (entry.getValue().data.size() == 0)
it.remove();
}
}
if (has_action(peek.nonguard))
rollback_rope(peek.nonguard, false);
rollback_rope(peek.rope, true);
}
/**
* Check whether a logical has some action.
*
* @param rope The logical.
* @return boolean if the logical has some action, false otherwise.
*/
static boolean has_action(Logical rope) {
Handler.Rope<Clause> data = rope.data;
for (int i = 0; i < data.size(); i++) {
Clause clause = data.get(i);
if (clause.creator == stage)
return true;
if (clause.remover == stage)
return true;
}
return false;
}
/**
* Rollback clauses from a logical.
*
* @param rope The logical.
* @param update The update flag.
*/
static void rollback_rope(Logical rope, boolean update) {
Handler.Rope<Clause> data = rope.data;
int j = 0;
for (int i = 0; i < data.size(); i++) {
Clause clause = data.get(i);
if (clause.creator == stage) {
rope.count--;
} else {
if (clause.remover == stage) {
if (update)
clause.remover = Store.UNDEF_INT;
rope.count++;
}
data.set(j++, clause);
}
}
data.removeRange(j, data.size());
rope.cache = null;
}
/*********************************************************************/
/* Clause Addition */
/*********************************************************************/
/**
* Enhance the knowledge base by a claus or predicate.
*
* @param functor The functor.
* @param arity The arity.
* @param clause_or_pred The clause or predicate.
*/
public static void add(String functor, int arity,
Object clause_or_pred) {
add_clause(functor, arity, clause_or_pred, MASK_ADD_BOTTOM);
}
/**
* Enhance the knowledge base by a claus or predicate.
*
* @param functor The functor.
* @param arity The arity.
* @param clause_or_pred The clause or predicate.
* @param flags The flags.
*/
public static void add_clause(String functor, int arity,
Object clause_or_pred, int flags) {
Handler.Rope<Provable> temp = kb.get(functor);
if (temp == null) {
temp = new Handler.Rope<>();
kb.put(functor, temp);
}
Provable peek = (arity < temp.size() ? temp.get(arity) : null);
if (is_clause(clause_or_pred)) {
if (peek == null || peek.remover != Store.UNDEF_INT) {
Provable res = make_defined(Machine.VOID_ARGS);
if (peek != null)
res.overlay = peek;
if ((flags & MASK_ADD_DYNAMIC) != 0)
res.flags |= MASK_PRED_DYNAMIC;
while (arity >= temp.size())
temp.add(null);
temp.set(arity, res);
peek = res;
} else {
if (!is_logical(peek.rope))
throw Machine.make_error(new Compound("permission_error",
new Object[]{"modify", "static_procedure",
Machine.make_indicator(functor, arity)}));
if ((flags & MASK_ADD_DYNAMIC) != 0)
if ((peek.flags & MASK_PRED_DYNAMIC) == 0)
throw Machine.make_error(new Compound("permission_error",
new Object[]{"modify", "static_procedure",
Machine.make_indicator(functor, arity)}));
}
if ((flags & MASK_ADD_DYNAMIC) == 0)
((Clause) clause_or_pred).shard = engine.partition;
add_peek(peek, (Clause) clause_or_pred, flags);
} else {
if (peek == null || peek.remover != Store.UNDEF_INT) {
Provable res = (Provable) clause_or_pred;
if (peek != null)
res.overlay = peek;
while (arity >= temp.size())
temp.add(null);
temp.set(arity, res);
} else {
throw Machine.make_error(new Compound("permission_error",
new Object[]{"coerce", "procedure",
Machine.make_indicator(functor, arity)}));
}
}
}
public static void add_peek(Provable peek, Clause clause, int flags) {
add_rope(peek.rope, clause, flags);
Object idxval = clause.idxval;
if (idxval == UNDEF_OBJ) {
Iterator<Map.Entry<Object, Logical>> it = peek.idxmap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Object, Logical> entry = it.next();
add_rope(entry.getValue(), clause, flags);
}
add_rope(peek.nonguard, clause, flags);
} else {
Logical value = peek.idxmap.get(idxval);
if (value == null) {
value = clone_rope(peek.nonguard);
peek.idxmap.put(idxval, value);
}
add_rope(value, clause, flags);
}
}
static void add_rope(Logical rope, Clause clause, int flags) {
if ((flags & MASK_ADD_BOTTOM) != 0) {
rope.data.add(clause);
} else {
rope.data.add(0, clause);
}
rope.count++;
rope.cache = null;
}
static Logical clone_rope(Logical rope) {
return new Logical(rope.cache, rope.count,
(Handler.Rope<Clause>) rope.data.clone());
}
/******************************************************************/
/* Clause Removal */
/******************************************************************/
/**
* Remove a clause from the knowledge base.
*
* @param functor The functor.
* @param arity The arity.
* @param clause The clause.
* @param flags The flags.
* @return boolean True if the clause was removed, false otherwise.
*/
public static boolean remove_clause(String functor, int arity,
Object clause, int flags) {
if (!is_clause(clause))
throw Machine.make_error(new Compound("permission_error",
new Object[]{"coerce", "procedure",
Machine.make_indicator(functor, arity)}));
Handler.Rope<Provable> temp = kb.get(functor);
if (temp == null)
return false;
Provable peek = (arity < temp.size() ? temp.get(arity) : null);
if (peek == null || peek.remover != Store.UNDEF_INT)
return false;
if (!is_logical(peek.rope))
throw Machine.make_error(new Compound("permission_error",
new Object[]{"modify", "static_procedure",
Machine.make_indicator(functor, arity)}));
return remove_peek(peek, (Clause) clause, flags);
}
static boolean remove_peek(Provable peek, Clause clause, int flags) {
if (clause.remover != Store.UNDEF_INT)
return false;
if (!remove_rope(peek.rope, clause, flags))
return false;
Object idxval = clause.idxval;
if (idxval == UNDEF_OBJ) {
Iterator<Map.Entry<Object, Logical>> it = peek.idxmap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Object, Logical> entry = it.next();
remove_rope(entry.getValue(), clause, flags);
if (entry.getValue().data.size() == 0)
it.remove();
}
remove_rope(peek.nonguard, clause, flags);
} else {
Logical value = peek.idxmap.get(idxval);
remove_rope(value, clause, flags);
if (value.data.size() == 0)
peek.idxmap.remove(idxval);
}
clause.remover = stage;
return true;
}
static boolean remove_rope(Logical rope, Clause clause, int flags) {
Handler.Rope<Clause> data = rope.data;
int index;
if ((flags & MASK_REMOVE_BOTTOM) == 0) {
index = data.indexOf(clause);
} else {
index = data.lastIndexOf(clause);
}
if (index == -1)
return false;
if (clause.creator == stage)
data.remove(index);
rope.count--;
rope.cache = null;
return true;
}
}