- (SG/X)ML-like syntax for queries
- logic engine in filter
- Note: this is an offline approach
- Rationale: only knowledge maintenance
embedded logic
<query kit=pl src=local.pl cmd=X:email_address(X)>
<param format=" \%s">
<param result="">
<param display="<h4>The query</h4>">
<param header="<h4>The adresses</h4> <ul>">
<param footer="</ul>">
email_address(E) :-
person(X),
property(X,name:N),
property(X,familyname:F),
email(X,E),
cout(['', N,' ',F,' has email adress ']),
cout([ '<a href=mailto:', E, '>', E, '</a>',nl]).
</query>
query pl = new query("kit=pl src=remote.pl");
pl.eval("X:assistant(X)");
String res = null;
while ( (res = pl.result()) != null ) {
System.out.println(" " + res);
}
- maintaining knowledge is difficult
- don't replicate, otherwise ...
- so we need to access knowledge from remote sources
- and possibly mix remote and local knowledge
- Solution: url-enabled consults
- Problem: availability of the (VU) server
- queries may clash, we need seperate 'engines'
- this is static, the next step is dynamic: signed applets
- this is research code, not production code
slide: Remarks
interface query {
void source(in string file);
long eval(in string cmd);
string result(in long id);
oneway void halt();
};
- knowledge management with logic is feasible
- has applications in document engineering and ...
- embedding is relatively efficient
- can be done in multiple ways
- corba enabled logic services are possible
- true logic is hard to debug
slide: Conclusions
- Many flavors: Sicstus, ...
- Modules do not suffice - ...
- Requirements: low overhead, natural syntax
- Additional requirements:
binding with native objects
slide: Objects in Prolog
- native bindings are mostly for functions only
- Java, however, provides an example
- Let's first look at objects in Prolog,
and then their possibly native realization
slide: Native Objects
- representation -- object(Handler,Class,ID,REF,Ancestors)
- object definition -- class_method(This,...)
- object invocation -- self(This):method(...)
- state variables representation -- value(ID,Key,Value)
- state variable access -- var(Key) = Value, Var = value(key)
- native binding - native(Handler,Method,Result)
slide: Objects in Prolog
requirements
- low overhead, especially when not needed
- natural syntax for object clause definitions
- support for native objects
midi(This):midi, // create midi object
Self = self(This),
Self:open('a.mid'),
Self:header(0,1,480),
Self:track(start),
Self:melody([48,50,51,53,55]), // c d es f g, minor indeed
Self:track(end), // end track
midi
:- use(library(midi:[midi,lily,music,process])).
:- declare(midi:object,class(midi),[handler]).
midi_midi(This) :- // constructor
midi(This):handler(H), // gets Handler from class
declare(H,new(midi(This)),[],[],_).
native methods
midi_read(This,F) :- native(_,This,read(F),_).
midi_analyse(This,I,O) :- native(_,This,analyse(I,O),_).
midi_open(This,F) :- native(_,This,open(F),_).
midi_header(This,M) :- native(_,This,header(M,0,480),_).
midi_track(This,X) :- native(_,This,track(X),_).
midi_tempo(This,X) :- native(_,This,tempo(X),_).
midi_event(This,D,C,M,T,V) :-
native(_,This,event(D,C,M,T,V),_).
midi_note(This,D,C,T,V) :-
Self = midi(This), // cast to midi
Self:event(D,C,note_on,T,V),
Self:event(D,C,note_off,T,V).
midi_melody(This,L) :- self(This):melody(480,1,L,64).
midi_melody(_This,_,_,[],_).
midi_melody(This,D,C,[X|R],V) :-
Self = self(This),
Self:note(D,C,X,V),
midi_melody(This,D,C,R,V). // direct invocation
- method call - check ID is a REF
- declaration - call (native) constructor
- mapping creation and method calls -- through native support
- native support -- binding: object_handler and query_event
- native support -- classes: the usual (hush) hierarchy
e.g. obscure
and kit
slide: Native Objects in Prolog
- generic binding for (pl) kit - with secondary handler dictionary
- handler hierarchy -- obscure, handler, event, kit, query
- downcall - via smart pointer vm
- upcall - via embedded vm in handler
slide: C++ bindings
class query_object : public kit_object { kit_object
public:
query_object(kit* q, char* n = "query:object") : kit_object(q,n) { }
object_handler* _create(query* q, char* n = "query:object") {
return new query_object(q,n);
}
int operator()();
};
int kit_object::operator()() {
event* e = _event;
vm<kit> self(e); // smart pointer
string method = e->_method();
if (method == "kit") { // constructor
kit* q = new kit(e->arg(1));
_register(q);
result( reference((void*)q) );
} else if (method == "eval") {
long res = self->eval(e->arg(1));
result( itoa(res) );
} else if (method == "result") {
char* res = self->result( atoi(e->arg(1)) );
result(res);
} else { // dispatch up in the hierarchy
return handler_object::operator()();
}
return 0;
}
event* handler::dispatch(event* e) {
_event = e;
if (_vmp) {
return ((vm*)_vmp)->dispatch(e);
} else {
if (e->thekit()) tk = e->thekit(); // AE
int result = this->operator()();
if (result != OK) return 0; // jrvosse
else return _event;
}
}
template <class T>
class vm { smart pointer class
public:
vm(event* e) {
int p = 0;
char* id = e->option("ref");
if (id) {
p = atoi(id);
}
_self = (T*) p;
}
virtual inline T* operator->() { return _self; }
private:
T* _self;
};
- See some more examples
pointer.c
and pointer.pl.
- Objects - in a mix of styles
- With native support - similar to hush-java support
- key-value transfer of native calls
- virtuality, operator overloading, nested calls, native support
- now we need concurrency ...
- remember query: we do have distribution already
slide: Conclusions
- representation if C++ peer: self pointer
- object/method function call: native functions
- cast self pointer to object: smart vm
slide: Native Objects in Java
package hush.dv.api;
class obscure {
public int _self; // peer object pointer
...
};
public class handler extends obscure {
public static kit tk;
protected Event _event;
public Event dispatch(event ev) {
_event = (Event) ev;
operator();
return _event;
}
public int operator() {
...
return OK;
}
};
package hush.dv.api;
public class kit extends handler {
public kit() { _self = init(); }
protected kit(int x) { }
private native int init();
public native void source(String cmd);
public native void eval(String cmd);
public String result() {
String _result = getresult();
if (_result.equals("-")) return null;
else return _result;
}
private native String getresult();
public native void bind(String cmd, handler h);
...
};
include @lt;hush/hush.h>
include @lt;hush/java.h>
include @lt;native/hush_dv_api_kit.h>
#define method(X) Java_hush_dv_api_kit_##X
JNIEXPORT jint JNICALL method(init)(JNIEnv *env, jobject obj)
{
jint result = (jint) kit::_default; // (jint) new kit();
if (!result) {
kit* x = new kit("tk");
session::_default->_register(x);
result = (jint) x;
}
return result;
}
JNIEXPORT jstring JNICALL method(getresult)(JNIEnv *env, jobject obj)
{
java_vm vm(env,obj);
char *s = vm->result();
if (s) return vm.string(s);
else return vm.string("-");
}
JNIEXPORT void JNICALL method(bind)(JNIEnv *env, jobject obj,
jstring s, jobject o)
{
java_vm vm(env,obj);
java_vm* vmp = new java_vm(env,o,"Handler");
const char *str = vm.get(s);
handler* h = new handler();
session::_default->_register(h);
h->_vmp = vmp;
h->_register(vmp);
vm->bind(str,h);
vm.release(s, str);
}
handler::dispatch
event* handler::dispatch(event* e) {
_event = e;
if (_vmp) {
return ((vm*)_vmp)->dispatch(e);
} else {
int result = this->operator()();
if (result != OK) return 0;
else return _event;
}
}
#include <hush/vm.h>
#include <jni.h>
template< class T >
class java_vm : public vm< T > {
public:
java_vm(JNIEnv* env_, jobject obj_) {
_env = env_;
_obj = obj_;
_self = self();
}
...
event* dispatch(event* e) { java dispatch
call("dispatch",(int)e);
return e;
}
T* operator->() { return _self; }
T* self() {
jfieldID fid = fieldID("_self","I");
return (T*) _env->GetIntField( _obj, fid);
}
void call(const char* md, int i) { // void (*)(int)
jmethodID mid = methodID(md,"(I)V");
_env->CallVoidMethod(_obj, mid, i);
}
private:
JNIEnv* _env;
jobject _obj;
T* _self;
};