Java "theatre"

Admin User, created Apr 18. 2025
         
package nova;
import nova.envir.ComputeElem;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TimerTask;
/**
* 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 theatre {
/**************************************************************/
/* Main API */
/**************************************************************/
/**
* Initializes the Prolog interpreter.
*/
public static void init() {
Store.set_stage(0);
Store.set_partition("user");
}
/**
* Post a message to the Prolog interpreter.
*
* @param message The message.
*/
public static void post(Object message) {
Machine.register_signal("main", message);
Machine.invoke_interrupt("main");
}
/**
* Run a Prolog term once. The goal is run with auto-yield
* disabled and promises are not accepted.
*
* @param goal The Prolog term.
* @return boolean True or false.
*/
public static Object perform(Object goal) {
goal = new Store.Compound(".", new Object[]{goal, "[]"});
return Machine.launch(goal, "main", Machine.VOID_ARGS);
}
/**
* Run a Prolog term once. The goal is run with auto-yield
* enabled and promises are accepted.
*
* @param goal The Prolog term.
* @return boolean True or false.
*/
public static boolean perform_async(Object goal) {
goal = new Store.Compound(".", new Object[]{goal, "[]"});
return Machine.launch_async(goal, "main", Machine.VOID_ARGS);
}
/**************************************************************/
/* Register API */
/**************************************************************/
/**
* The flag indicates a non-void dispatch foreign function.
*/
public static int FFI_FUNC = 0x00000100;
/**
* Add a Java function to the knowledge base. The given
* function is invoked with rather slow argument copying. Also
* the function is wrapped and registered as a special, therefore
* not eligible to neck optimization.
*
* @param functor The functor.
* @param arity The arity.
* @param func The Java function.
* @param flags The flags.
*/
public static void register(String functor, int arity, Handler.Builtin func, int flags) {
Store.Provable res;
if ((flags & FFI_FUNC) != 0) {
res = special.make_special((args) -> invoke_func(func, args));
} else {
res = special.make_special((args) -> invoke(func, args));
}
Store.add(functor, arity, res);
}
private static Object invoke(Handler.Builtin func, Object[] args) {
Object[] temp = new Object[args.length];
for (int i = 0; i < temp.length; i++)
temp[i] = Machine.deref(args[i]);
func.run(temp);
Machine.cont(((Store.Compound) Machine.call).args[1]);
return Boolean.TRUE;
}
private static Object invoke_func(Handler.Builtin func, Object[] args) {
Object[] temp = new Object[args.length - 1];
for (int i = 0; i < temp.length; i++)
temp[i] = Machine.deref(args[i]);
Object res = func.run(temp);
if (!Machine.unify(args[args.length - 1], res))
return Boolean.FALSE;
Machine.cont(((Store.Compound) Machine.call).args[1]);
return Boolean.TRUE;
}
/*****************************************************************/
/* ir_object_new/1 and ir_object_current/3 */
/*****************************************************************/
/**
* ir_object_new(O):
* The predicate succeeds in O with a new Java object.
*/
private static boolean test_ir_object_new(Object[] args) {
HashMap<String, Object> res = new HashMap<>();
return Machine.exec_unify(args[0], res);
}
/**
* ir_object_current(O, K, V):
* The predicate succeeds in V with the value of the key K in the Java object O.
*/
private static boolean test_ir_object_current(Object[] args) {
Object obj = Machine.deref(Machine.exec_build(args[0]));
Object key = Machine.deref(Machine.exec_build(args[1]));
special.check_atom(key);
Object res;
if (obj instanceof HashMap) {
res = ((HashMap<String, Object>) obj).getOrDefault((String) key, Store.UNDEF_OBJ);
} else {
try {
Field field = obj.getClass().getField((String) key);
res = field.get(obj);
} catch (NullPointerException | NoSuchFieldException |
IllegalAccessException e) {
res = Store.UNDEF_OBJ;
}
}
if (res == Store.UNDEF_OBJ)
return false;
return Machine.exec_unify(args[2], res);
}
/*****************************************************************/
/* ir_object_set/3 and ir_object_keys/2 */
/*****************************************************************/
/**
* ir_object_set(O, K, V):
* The predicate sets the value of the key K in the Java object O to V.
*/
private static boolean test_ir_object_set(Object[] args) {
Object obj = Machine.deref(Machine.exec_build(args[0]));
Object key = Machine.deref(Machine.exec_build(args[1]));
special.check_atom(key);
Object value = Machine.deref(Machine.exec_build(args[2]));
if (obj instanceof HashMap) {
((HashMap<String, Object>) obj).put((String) key, value);
} else {
try {
Field field = obj.getClass().getField((String) key);
field.set(obj, value);
} catch (NullPointerException | NoSuchFieldException |
IllegalAccessException e) {
throw Machine.make_error(new Store.Compound("permission_error",
new Object[]{"field", "modify", key}));
}
}
return true;
}
/**
* ir_object_keys(O, L):
* The predicate succeeds in L with the keys of the Java object O.
*/
private static boolean test_ir_object_keys(Object[] args) {
Object obj = Machine.deref(Machine.exec_build(args[0]));
Object res = special.set_to_list(((HashMap<String, Object>) obj).keySet());
return Machine.exec_unify(args[1], res);
}
/******************************************************************/
/* ir_float_value/2 */
/******************************************************************/
/**
* ir_float_value(P, H):
* If P is instantiated, then the predicate succeeds in H with the
* Java float of P, otherwise in P with the Prolog float of H.
*/
private static boolean test_ir_float_value(Object[] args) {
Object alpha = Machine.deref(Machine.exec_build(args[0]));
if (Store.is_variable(alpha)) {
Object beta = Machine.deref(Machine.exec_build(args[1]));
special.check_number(beta);
Object res = beta instanceof Double ? ComputeElem.norm_float((Double)beta) :
Double.valueOf(ComputeElem.narrow_float((Number)beta));
return Machine.unify(alpha, res);
} else {
special.check_number(alpha);
Object res = alpha instanceof Double ? alpha :
Double.valueOf(ComputeElem.narrow_float((Number)alpha));
return Machine.exec_unify(args[1], res);
}
}
/**************************************************************/
/* os_call_later/3 and os_call_cancel/1 */
/**************************************************************/
/**
* os_call_later(N, D, T): internal only
* The predicate succeeds in T with a new timer. As a side
* effect it schedules the compiled goal N to be executed
* after D milliseconds.
*/
private static boolean test_os_call_later(Object[] args) {
Object goal = Machine.deref(Machine.exec_build(args[0]));
runtime.check_goal(goal);
Object alpha = Machine.deref(Machine.exec_build(args[1]));
special.check_integer(alpha);
long delay = ((Number) alpha).longValue();
Object buf = Machine.ctx;
TimerTask tid = Machine.setDelay(() -> Machine.callback(goal, buf, Machine.VOID_ARGS), delay);
return Machine.exec_unify(args[2], tid);
}
/**
* os_call_cancel(T): internal only
* The predicate succeeds. As a side effect it cancels the timer T.
*/
private static boolean test_os_call_cancel(Object[] args) {
TimerTask tid = (TimerTask) Machine.deref(Machine.exec_build(args[0]));
tid.cancel();
return true;
}
/**************************************************************/
/* os_task_current/1, os_task_abort/2 and os_task_create/2 */
/**************************************************************/
/**
* os_task_current(E): internal only
* The predicate succeeds in E with the current task.
*/
private static boolean test_os_task_current(Object[] args) {
return Machine.exec_unify(args[0], Machine.ctx);
}
/**
* os_task_abort(E, M): internal only
* The predicate succeeds. As a side effect the task E gets
* the message M signalled.
*/
private static boolean test_os_task_abort(Object[] args) {
Object buf = Machine.deref(Machine.exec_build(args[0]));
Object msg = Machine.exec_build(args[1]);
msg = new Machine.copy_term().copy_term2(msg);
Machine.register_signal(buf, msg);
Machine.invoke_interrupt(buf);
return true;
}
/**
* os_task_create(N, E): internal only
* The predicate succeeds in E with a new task for the compiled
* goal N. The task is scheduled to execute immediately.
*/
private static boolean test_os_task_create(Object[] args) {
Object goal = Machine.deref(Machine.exec_build(args[0]));
runtime.check_goal(goal);
Machine.Context buf = new Machine.Context();
Machine.setDelay(() -> Machine.task_async(goal, buf, Machine.VOID_ARGS), 0);
return Machine.exec_unify(args[1], buf);
}
/******************************************************************/
/* Theatre Init */
/******************************************************************/
public static void boot() {
// object specials
Store.add("ir_object_new", 1, special.make_check(theatre::test_ir_object_new));
Store.add("ir_object_current", 3, special.make_check(theatre::test_ir_object_current));
Store.add("ir_object_set", 3, special.make_check(theatre::test_ir_object_set));
Store.add("ir_object_keys", 2, special.make_check(theatre::test_ir_object_keys));
// scalar specials
Store.add("ir_float_value", 2, special.make_check(theatre::test_ir_float_value));
// system specials, coroutines, internal only
Store.add("os_call_later", 3, special.make_check(theatre::test_os_call_later));
Store.add("os_call_cancel", 1, special.make_check(theatre::test_os_call_cancel));
Store.add("os_task_current", 1, special.make_check(theatre::test_os_task_current));
Store.add("os_task_abort", 2, special.make_check(theatre::test_os_task_abort));
Store.add("os_task_create", 2, special.make_check(theatre::test_os_task_create));
}
}