1/* Part of JPL -- SWI-Prolog/Java interface 2 3 Author: Paul Singleton, Fred Dushin and Jan Wielemaker 4 E-mail: paul@jbgb.com 5 WWW: http://www.swi-prolog.org 6 Copyright (c) 2004-2020, Paul Singleton 7 All rights reserved. 8 9 Redistribution and use in source and binary forms, with or without 10 modification, are permitted provided that the following conditions 11 are met: 12 13 1. Redistributions of source code must retain the above copyright 14 notice, this list of conditions and the following disclaimer. 15 16 2. Redistributions in binary form must reproduce the above copyright 17 notice, this list of conditions and the following disclaimer in 18 the documentation and/or other materials provided with the 19 distribution. 20 21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 POSSIBILITY OF SUCH DAMAGE. 33*/ 34 35:- module(jpl, 36 [ jpl_get_default_jvm_opts/1, 37 jpl_set_default_jvm_opts/1, 38 jpl_get_actual_jvm_opts/1, 39 jpl_pl_lib_version/1, 40 jpl_c_lib_version/1, 41 jpl_pl_syntax/1, 42 jpl_new/3, 43 jpl_call/4, 44 jpl_get/3, 45 jpl_set/3, 46 jpl_servlet_byref/3, 47 jpl_servlet_byval/3, 48 jpl_class_to_classname/2, 49 jpl_class_to_type/2, 50 jpl_classname_to_class/2, 51 jpl_classname_to_type/2, % name does not reflect that it deals with entity names 52 jpl_datum_to_type/2, 53 jpl_entityname_to_type/2, % new alias for jpl_classname_to_type/2 54 jpl_false/1, 55 jpl_is_class/1, 56 jpl_is_false/1, 57 jpl_is_null/1, 58 jpl_is_object/1, 59 jpl_is_object_type/1, 60 jpl_is_ref/1, 61 jpl_is_true/1, 62 jpl_is_type/1, 63 jpl_is_void/1, 64 jpl_null/1, 65 jpl_object_to_class/2, 66 jpl_object_to_type/2, 67 jpl_primitive_type/1, 68 jpl_ref_to_type/2, 69 jpl_true/1, 70 jpl_type_to_class/2, 71 jpl_type_to_classname/2, % name does not reflect that it deals with entity names 72 jpl_type_to_entityname/2, % new alias for jpl_type_to_classname/2 73 jpl_void/1, 74 jpl_array_to_length/2, 75 jpl_array_to_list/2, 76 jpl_datums_to_array/2, 77 jpl_enumeration_element/2, 78 jpl_enumeration_to_list/2, 79 jpl_hashtable_pair/2, 80 jpl_iterator_element/2, 81 jpl_list_to_array/2, 82 jpl_terms_to_array/2, 83 jpl_array_to_terms/2, 84 jpl_map_element/2, 85 jpl_set_element/2 86 ]). 87:- autoload(library(apply),[maplist/2]). 88:- autoload(library(debug),[debugging/1,debug/3]). 89:- autoload(library(lists), 90 [member/2,nth0/3,nth1/3,append/3,flatten/2,select/3]). 91:- autoload(library(shlib),[load_foreign_library/1]).
100% suppress debugging this library 101:- set_prolog_flag(generate_debug_info, false).
'java.lang.String'
'[I'
or 'Ljava.lang.String;'
class(_,_)
or array(_)
, e.g. class([java,util],['Date'])
If X is an object (non-array) type or descriptor and Params is a list of values or references, then V is the result of an invocation of that type's most specifically-typed constructor to whose respective formal parameters the actual Params are assignable (and assigned).
If X is an array type or descriptor and Params is a list of values or references, each of which is (independently) assignable to the array element type, then V is a new array of as many elements as Params has members, initialised with the respective members of Params.
If X is an array type or descriptor and Params is a non-negative integer N, then V is a new array of that type, with N elements, each initialised to Java's appropriate default value for the type.
If V is literally {Term}
then we attempt to convert a
new org.jpl7.Term
instance to
a corresponding term; this is of little obvious use here, but is
consistent with jpl_call/4 and jpl_get/3.
132jpl_new(X, Params, V) :-
133 ( var(X)
134 -> throwme(jpl_new,x_is_var)
135 ; jpl_is_type(X) % NB Should check for "instantiable type"? Also accepts "double" for example.
136 -> Type = X
137 ; atom(X) % an atom not captured by jpl_is_type/1 e.g. 'java.lang.String', '[L', even "void"
138 -> ( jpl_entityname_to_type(X, Type)
139 -> true
140 ; throwme(jpl_new,x_not_classname(X))
141 )
142 ; throwme(jpl_new,x_not_instantiable(X))
143 ),
144 jpl_new_1(Type, Params, Vx),
145 ( nonvar(V),
146 V = {Term} % yucky way of requesting Term->term conversion
147 -> ( jni_jref_to_term(Vx, TermX) % fails if Vx is not a JRef to a org.jpl7.Term
148 -> Term = TermX
149 ; throwme(jpl_new,not_a_jpl_term(Vx))
150 )
151 ; V = Vx
152 ).
Tx can be a class(_,_)
or array(_)
type.
Params must be a proper list of constructor parameters.
At exit, Vx is bound to a JPL reference to a new, initialised instance of Tx
165jpl_new_1(class(Ps,Cs), Params, Vx) :- 166 !, % green (see below) 167 Tx = class(Ps,Cs), 168 ( var(Params) 169 -> throwme(jpl_new_class,params_is_var) 170 ; \+ is_list(Params) 171 -> throwme(jpl_new_class,params_is_not_list(Params)) 172 ; true 173 ), 174 length(Params, A), % the "arity" of the required constructor 175 jpl_type_to_class(Tx, Cx), % throws Java exception if class is not found 176 N = '<init>', % JNI's constructor naming convention for GetMethodID() 177 Tr = void, % all constructors have this return "type" 178 findall( 179 z3(I,MID,Tfps), 180 jpl_method_spec(Tx, I, N, A, _Mods, MID, Tr, Tfps), % cached 181 Z3s 182 ), 183 ( Z3s == [] % no constructors which require the given qty of parameters? 184 -> ( jpl_call(Cx, isInterface, [], @(true)) 185 -> throwme(jpl_new_class,class_is_interface(Tx)) 186 ; throwme(jpl_new_class,class_without_constructor(Tx,A)) 187 ) 188 ; ( catch( 189 jpl_datums_to_types(Params, Taps), % infer actual parameter types 190 % 2020-07-21: make catcher's 1st context arg an "anonvar" instead of a overspecified predicate indicator 191 error(type_error(acyclic,Te),context(_,Msg)), 192 throwme(jpl_new_class,acyclic(Te,Msg)) % rethrow 193 ) 194 -> true 195 ; throwme(jpl_new_class,bad_jpl_datum(Params)) 196 ), 197 findall( 198 z3(I,MID,Tfps), % select constructors to which actual parameters are assignable 199 ( member(z3(I,MID,Tfps), Z3s), 200 jpl_types_fit_types(Taps, Tfps) % assignability test: actual parameter types "fit" formal parameter types? 201 ), 202 Z3sA 203 ), 204 ( Z3sA == [] % no type-assignable constructors? 205 -> ( Z3s = [_] 206 -> throwme(jpl_new_class,single_constructor_mismatch(Tx/A)) 207 ; throwme(jpl_new_class,any_constructor_mismatch(Params)) 208 ) 209 ; Z3sA = [z3(I,MID,Tfps)] 210 -> true 211 ; jpl_z3s_to_most_specific_z3(Z3sA, z3(I,MID,Tfps)) 212 -> true 213 ; throwme(jpl_new_class,constructor_multimatch(Params)) 214 ) 215 ), 216 catch( 217 jNewObject(Cx, MID, Tfps, Params, Vx), 218 error(java_exception(_), 'java.lang.InstantiationException'), 219 throwme(jpl_new_class,class_is_abstract(Tx)) % Rethrow 220 ), 221 jpl_cache_type_of_ref(Tx, Vx). % since we know it 222 223jpl_new_1(array(T), Params, Vx) :- 224 !, 225 ( var(Params) 226 -> throwme(jpl_new_array,params_is_var) 227 ; integer(Params) % integer I -> array[0..I-1] of default values 228 -> ( Params >= 0 229 -> Len is Params 230 ; throwme(jpl_new_array,params_is_negative(Params)) 231 ) 232 ; is_list(Params) % [V1,..VN] -> array[0..N-1] of respective values 233 -> length(Params, Len) 234 ), 235 jpl_new_array(T, Len, Vx), % NB may throw out-of-memory exception 236 ( nth0(I, Params, Param), % nmember fails silently when Params is integer 237 jpl_set(Vx, I, Param), 238 fail 239 ; true 240 ), 241 jpl_cache_type_of_ref(array(T), Vx). % since we know it 242 243jpl_new_1(T, _Params, _Vx) :- % doomed attempt to create new primitive type instance (formerly a dubious completist feature :-) 244 jpl_primitive_type(T), 245 !, 246 throwme(jpl_new_primitive,primitive_type_requested(T)). 247 % ( var(Params) 248 % -> throwme(jpl_new_primitive,params_is_var) 249 % ; Params == [] 250 % -> jpl_primitive_type_default_value(T, Vx) 251 % ; Params = [Param] 252 % -> jpl_primitive_type_term_to_value(T, Param, Vx) 253 % ; throwme(jpl_new_primitive,params_is_bad(Params)) 254 % ). 255 256jpl_new_1(T, _, _) :- throwme(jpl_new_catchall,catchall(T)).
263jpl_new_array(boolean, Len, A) :- 264 jNewBooleanArray(Len, A). 265jpl_new_array(byte, Len, A) :- 266 jNewByteArray(Len, A). 267jpl_new_array(char, Len, A) :- 268 jNewCharArray(Len, A). 269jpl_new_array(short, Len, A) :- 270 jNewShortArray(Len, A). 271jpl_new_array(int, Len, A) :- 272 jNewIntArray(Len, A). 273jpl_new_array(long, Len, A) :- 274 jNewLongArray(Len, A). 275jpl_new_array(float, Len, A) :- 276 jNewFloatArray(Len, A). 277jpl_new_array(double, Len, A) :- 278 jNewDoubleArray(Len, A). 279jpl_new_array(array(T), Len, A) :- 280 jpl_type_to_class(array(T), C), 281 jNewObjectArray(Len, C, @(null), A). % initialise each element to null 282jpl_new_array(class(Ps,Cs), Len, A) :- 283 jpl_type_to_class(class(Ps,Cs), C), 284 jNewObjectArray(Len, C, @(null), A).
<jref>(1552320)
(for static or instance methods)'java.util.Date'
(for static methods only)'Ljava.util.Date;'
(for static methods only)class([java,util],['Date'])
(for static methods only)MethodName should be a method name (as an atom) (may involve dynamic overload resolution based on inferred types of params)
Params should be a proper list (perhaps empty) of suitable actual parameters for the named method.
The class or object may have several methods with the given name; JPL will resolve (per call) to the most appropriate method based on the quantity and inferred types of Params. This resolution mimics the corresponding static resolution performed by Java compilers.
Finally, an attempt will be made to unify Result with the method's returned value,
or with @(void)
(the compound term with name @
and argument void
) if it has none.
306jpl_call(X, Mspec, Params, R) :-
307 ( jpl_object_to_type(X, Type) % the usual case (goal fails safely if X is var or rubbish)
308 -> Obj = X,
309 Kind = instance
310 ; var(X)
311 -> throwme(jpl_call,arg1_is_var)
312 ; atom(X)
313 -> ( jpl_entityname_to_type(X, Type) % does this attempt to load the class?
314 -> ( jpl_type_to_class(Type, ClassObj)
315 -> Kind = static
316 ; throwme(jpl_call,no_such_class(X))
317 )
318 ; throwme(jpl_call,arg1_is_bad(X))
319 )
320 ; X = class(_,_)
321 -> Type = X,
322 jpl_type_to_class(Type, ClassObj),
323 Kind = static
324 ; X = array(_)
325 -> throwme(jpl_call,arg1_is_array(X))
326 ; throwme(jpl_call,arg1_is_bad(X))
327 ),
328 ( atom(Mspec) % the usual case, i.e. a method name
329 -> true
330 ; var(Mspec)
331 -> throwme(jpl_call,mspec_is_var)
332 ; throwme(jpl_call,mspec_is_bad(Mspec))
333 ),
334 ( is_list(Params)
335 -> ( catch(
336 jpl_datums_to_types(Params, Taps),
337 % 2020-07-21: make catcher's 1st context arg an "anonvar" instead of a overspecified predicate indicator
338 error(type_error(acyclic,Te),context(_,Msg)),
339 throwme(jpl_call,acyclic(Te,Msg)) % rethrow
340 )
341 -> true
342
343 ; throwme(jpl_call,nonconvertible_params(Params))
344 ),
345 length(Params, A)
346 ; var(Params)
347 -> throwme(jpl_call,arg3_is_var)
348 ; throwme(jpl_call,arg3_is_bad(Params))
349 ),
350 ( Kind == instance
351 -> jpl_call_instance(Type, Obj, Mspec, Params, Taps, A, Rx)
352 ; jpl_call_static(Type, ClassObj, Mspec, Params, Taps, A, Rx)
353 ),
354 ( nonvar(R),
355 R = {Term} % yucky way of requesting Term->term conversion
356 -> ( jni_jref_to_term(Rx, TermX) % fails if Rx isn't a JRef to a org.jpl7.Term
357 -> Term = TermX
358 ; throwme(jpl_call,not_a_jpl_term(Rx))
359 )
360 ; R = Rx
361 ).
371jpl_call_instance(Type, Obj, Mname, Params, Taps, A, Rx) :-
372 findall( % get remaining details of all accessible methods of Obj's class (as denoted by Type)
373 z5(I,Mods,MID,Tr,Tfps),
374 jpl_method_spec(Type, I, Mname, A, Mods, MID, Tr, Tfps),
375 Z5s
376 ),
377 ( Z5s = []
378 -> throwme(jpl_call_instance,no_such_method(Mname/A))
379 ; findall(
380 z5(I,Mods,MID,Tr,Tfps), % those to which Params is assignable
381 ( member(z5(I,Mods,MID,Tr,Tfps), Z5s),
382 jpl_types_fit_types(Taps, Tfps) % assignability test: actual param types "fit" formal param types
383 ),
384 Z5sA % Params-assignable methods
385 ),
386 ( Z5sA == []
387 -> throwme(jpl_call_instance,param_not_assignable(Params))
388 ; Z5sA = [z5(I,Mods,MID,Tr,Tfps)]
389 -> true % exactly one applicable method
390 ; jpl_z5s_to_most_specific_z5(Z5sA, z5(I,Mods,MID,Tr,Tfps))
391 -> true % exactly one most-specific applicable method
392 ; throwme(jpl_call_instance,multiple_most_specific(Mname/Params))
393 )
394 ),
395 ( member(static, Mods) % if the chosen method is static
396 -> jpl_object_to_class(Obj, ClassObj), % get a java.lang.Class instance which personifies Obj's class
397 jpl_call_static_method(Tr, ClassObj, MID, Tfps, Params, Rx) % call static method w.r.t. associated Class object
398 ; jpl_call_instance_method(Tr, Obj, MID, Tfps, Params, Rx) % else call (non-static) method w.r.t. object itself
399 ).
410jpl_call_static(Type, ClassObj, Mname, Params, Taps, A, Rx) :-
411 findall( % get all accessible static methods of the class denoted by Type and ClassObj
412 z5(I,Mods,MID,Tr,Tfps),
413 ( jpl_method_spec(Type, I, Mname, A, Mods, MID, Tr, Tfps),
414 member(static, Mods)
415 ),
416 Z5s
417 ),
418 ( Z5s = []
419 -> throwme(jpl_call_static,no_such_method(Mname))
420 ; findall(
421 z5(I,Mods,MID,Tr,Tfps),
422 ( member(z5(I,Mods,MID,Tr,Tfps), Z5s),
423 jpl_types_fit_types(Taps, Tfps) % assignability test: actual param types "fit" formal param types
424 ),
425 Z5sA % Params-assignable methods
426 ),
427 ( Z5sA == []
428 -> throwme(jpl_call_static,param_not_assignable(Params))
429 ; Z5sA = [z5(I,Mods,MID,Tr,Tfps)]
430 -> true % exactly one applicable method
431 ; jpl_z5s_to_most_specific_z5(Z5sA, z5(I,Mods,MID,Tr,Tfps))
432 -> true % exactly one most-specific applicable method
433 ; throwme(jpl_call_instance,multiple_most_specific(Mname/Params))
434 )
435 ),
436 jpl_call_static_method(Tr, ClassObj, MID, Tfps, Params, Rx).
441jpl_call_instance_method(void, Class, MID, Tfps, Ps, R) :- 442 jCallVoidMethod(Class, MID, Tfps, Ps), 443 jpl_void(R). 444jpl_call_instance_method(boolean, Class, MID, Tfps, Ps, R) :- 445 jCallBooleanMethod(Class, MID, Tfps, Ps, R). 446jpl_call_instance_method(byte, Class, MID, Tfps, Ps, R) :- 447 jCallByteMethod(Class, MID, Tfps, Ps, R). 448jpl_call_instance_method(char, Class, MID, Tfps, Ps, R) :- 449 jCallCharMethod(Class, MID, Tfps, Ps, R). 450jpl_call_instance_method(short, Class, MID, Tfps, Ps, R) :- 451 jCallShortMethod(Class, MID, Tfps, Ps, R). 452jpl_call_instance_method(int, Class, MID, Tfps, Ps, R) :- 453 jCallIntMethod(Class, MID, Tfps, Ps, R). 454jpl_call_instance_method(long, Class, MID, Tfps, Ps, R) :- 455 jCallLongMethod(Class, MID, Tfps, Ps, R). 456jpl_call_instance_method(float, Class, MID, Tfps, Ps, R) :- 457 jCallFloatMethod(Class, MID, Tfps, Ps, R). 458jpl_call_instance_method(double, Class, MID, Tfps, Ps, R) :- 459 jCallDoubleMethod(Class, MID, Tfps, Ps, R). 460jpl_call_instance_method(array(_), Class, MID, Tfps, Ps, R) :- 461 jCallObjectMethod(Class, MID, Tfps, Ps, R). 462jpl_call_instance_method(class(_,_), Class, MID, Tfps, Ps, R) :- 463 jCallObjectMethod(Class, MID, Tfps, Ps, R).
468jpl_call_static_method(void, Class, MID, Tfps, Ps, R) :- 469 jCallStaticVoidMethod(Class, MID, Tfps, Ps), 470 jpl_void(R). 471jpl_call_static_method(boolean, Class, MID, Tfps, Ps, R) :- 472 jCallStaticBooleanMethod(Class, MID, Tfps, Ps, R). 473jpl_call_static_method(byte, Class, MID, Tfps, Ps, R) :- 474 jCallStaticByteMethod(Class, MID, Tfps, Ps, R). 475jpl_call_static_method(char, Class, MID, Tfps, Ps, R) :- 476 jCallStaticCharMethod(Class, MID, Tfps, Ps, R). 477jpl_call_static_method(short, Class, MID, Tfps, Ps, R) :- 478 jCallStaticShortMethod(Class, MID, Tfps, Ps, R). 479jpl_call_static_method(int, Class, MID, Tfps, Ps, R) :- 480 jCallStaticIntMethod(Class, MID, Tfps, Ps, R). 481jpl_call_static_method(long, Class, MID, Tfps, Ps, R) :- 482 jCallStaticLongMethod(Class, MID, Tfps, Ps, R). 483jpl_call_static_method(float, Class, MID, Tfps, Ps, R) :- 484 jCallStaticFloatMethod(Class, MID, Tfps, Ps, R). 485jpl_call_static_method(double, Class, MID, Tfps, Ps, R) :- 486 jCallStaticDoubleMethod(Class, MID, Tfps, Ps, R). 487jpl_call_static_method(array(_), Class, MID, Tfps, Ps, R) :- 488 jCallStaticObjectMethod(Class, MID, Tfps, Ps, R). 489jpl_call_static_method(class(_,_), Class, MID, Tfps, Ps, R) :- 490 jCallStaticObjectMethod(Class, MID, Tfps, Ps, R).
Fspec can be
Finally, an attempt will be made to unify V with the retrieved value or object reference.
Examples
jpl_get('java.awt.Cursor', 'NE_RESIZE_CURSOR', Q). Q = 7. jpl_new(array(class([java,lang],['String'])), [for,while,do,if,then,else,try,catch,finally], A), jpl_get(A, 3-5, B). B = [if, then, else].
522jpl_get(X, Fspec, V) :-
523 ( jpl_object_to_type(X, Type)
524 -> Obj = X,
525 jpl_get_instance(Type, Type, Obj, Fspec, Vx) % pass Type twice for FAI
526 ; var(X)
527 -> throwme(jpl_get,arg1_is_var)
528 ; jpl_is_type(X) % e.g. class([java,lang],['String']), array(int)
529 -> Type = X,
530 ( jpl_type_to_class(Type, ClassObj)
531 -> jpl_get_static(Type, ClassObj, Fspec, Vx)
532 ; throwme(jpl_get,named_class_not_found(Type))
533 )
534 ; atom(X)
535 -> ( jpl_entityname_to_type(X, Type) % does this attempt to load the class? (NO!)
536 -> ( jpl_type_to_class(Type, ClassObj)
537 -> jpl_get_static(Type, ClassObj, Fspec, Vx)
538 ; throwme(jpl_get,named_class_not_found(Type))
539 )
540 ; throwme(jpl_get,arg1_is_bad(X))
541 )
542 ; throwme(jpl_get,arg1_is_bad_2(X))
543 ),
544 ( nonvar(V),
545 V = {Term} % yucky way of requesting Term->term conversion
546 -> ( jni_jref_to_term(Vx, TermX) % fails if Rx is not a JRef to a org.jpl7.Term
547 -> Term = TermX
548 ; throwme(jpl_get,not_a_jpl_term(X))
549 )
550 ; V = Vx
551 ).
563jpl_get_static(Type, ClassObj, Fname, Vx) :-
564 ( atom(Fname) % assume it's a field name
565 -> true
566 ; var(Fname)
567 -> throwme(jpl_get_static,arg2_is_var)
568 ; throwme(jpl_get_static,arg2_is_bad(Fname))
569 ),
570 % get static fields of the denoted class
571 findall(
572 z4(I,Mods,FID,Tf),
573 ( jpl_field_spec(Type, I, Fname, Mods, FID, Tf),
574 member(static, Mods)
575 ),
576 Z4s
577 ),
578 ( Z4s = []
579 -> throwme(jpl_get_static,no_such_field(Fname))
580 ; Z4s = [z4(I,_Mods,FID,Tf)]
581 -> jpl_get_static_field(Tf, ClassObj, FID, Vx)
582 ; throwme(jpl_get_static,multiple_fields(Fname))
583 ).
589jpl_get_instance(class(_,_), Type, Obj, Fname, Vx) :- 590 ( atom(Fname) % the usual case 591 -> true 592 ; var(Fname) 593 -> throwme(jpl_get_instance,arg2_is_var) 594 ; throwme(jpl_get_instance,arg2_is_bad(Fname)) 595 ), 596 findall( 597 z4(I,Mods,FID,Tf), 598 jpl_field_spec(Type, I, Fname, Mods, FID, Tf), 599 Z4s 600 ), 601 ( Z4s = [] 602 -> throwme(jpl_get_instance,no_such_field(Fname)) 603 ; Z4s = [z4(I,Mods,FID,Tf)] 604 -> ( member(static, Mods) 605 -> jpl_object_to_class(Obj, ClassObj), 606 jpl_get_static_field(Tf, ClassObj, FID, Vx) 607 ; jpl_get_instance_field(Tf, Obj, FID, Vx) 608 ) 609 ; throwme(jpl_get_instance,multiple_fields(Fname)) 610 ). 611 612 613jpl_get_instance(array(ElementType), _, Array, Fspec, Vx) :- 614 ( var(Fspec) 615 -> throwme(jpl_get_instance_array,arg2_is_var) 616 ; integer(Fspec) 617 -> ( Fspec < 0 % lo bound check 618 -> throwme(jpl_get_instance_array,arg2_is_bad(Fspec)) 619 ; jGetArrayLength(Array, Len), 620 Fspec >= Len % hi bound check 621 -> throwme(jpl_get_instance_array,arg2_is_too_large(Fspec)) 622 ; jpl_get_array_element(ElementType, Array, Fspec, Vx) 623 ) 624 ; Fspec = N-M % NB should we support e.g. 3-2 -> [] ? 625 -> ( integer(N), 626 integer(M) 627 -> ( N >= 0, 628 M >= N 629 -> jGetArrayLength(Array, Len), 630 ( N >= Len 631 -> throwme(jpl_get_instance_array,bad_range_low(N-M)) 632 ; M >= Len 633 -> throwme(jpl_get_instance_array,bad_range_high(N-M)) 634 ; jpl_get_array_elements(ElementType, Array, N, M, Vx) 635 ) 636 ; throwme(jpl_get_instance_array,bad_range_pair_values(N-M)) 637 ) 638 ; throwme(jpl_get_instance_array,bad_range_pair_types(N-M)) 639 ) 640 ; atom(Fspec) 641 -> ( Fspec == length % special-case for this solitary array "method" 642 -> jGetArrayLength(Array, Vx) 643 ; throwme(jpl_get_instance_array,no_such_field(Fspec)) 644 ) 645 ; throwme(jpl_get_instance_array,wrong_spec(Fspec)) 646 ).
659jpl_get_array_element(Type, Array, Index, Vc) :- 660 ( ( Type = class(_,_) 661 ; Type = array(_) 662 ) 663 -> jGetObjectArrayElement(Array, Index, Vr) 664 ; jpl_primitive_type(Type) 665 -> jni_type_to_xput_code(Type, Xc), 666 jni_alloc_buffer(Xc, 1, Bp), % one-element buf for a Type 667 jpl_get_primitive_array_region(Type, Array, Index, 1, Bp), 668 jni_fetch_buffer_value(Bp, 0, Vr, Xc), % zero-th element 669 jni_free_buffer(Bp) 670 ), 671 Vr = Vc. % redundant since Vc is always (?) unbound at call
Vs will always be unbound on entry
680jpl_get_array_elements(ElementType, Array, N, M, Vs) :- 681 ( ( ElementType = class(_,_) 682 ; ElementType = array(_) 683 ) 684 -> jpl_get_object_array_elements(Array, N, M, Vs) 685 ; jpl_get_primitive_array_elements(ElementType, Array, N, M, Vs) 686 ). 687 688 689jpl_get_instance_field(boolean, Obj, FieldID, V) :- 690 jGetBooleanField(Obj, FieldID, V). 691jpl_get_instance_field(byte, Obj, FieldID, V) :- 692 jGetByteField(Obj, FieldID, V). 693jpl_get_instance_field(char, Obj, FieldID, V) :- 694 jGetCharField(Obj, FieldID, V). 695jpl_get_instance_field(short, Obj, FieldID, V) :- 696 jGetShortField(Obj, FieldID, V). 697jpl_get_instance_field(int, Obj, FieldID, V) :- 698 jGetIntField(Obj, FieldID, V). 699jpl_get_instance_field(long, Obj, FieldID, V) :- 700 jGetLongField(Obj, FieldID, V). 701jpl_get_instance_field(float, Obj, FieldID, V) :- 702 jGetFloatField(Obj, FieldID, V). 703jpl_get_instance_field(double, Obj, FieldID, V) :- 704 jGetDoubleField(Obj, FieldID, V). 705jpl_get_instance_field(class(_,_), Obj, FieldID, V) :- 706 jGetObjectField(Obj, FieldID, V). 707jpl_get_instance_field(array(_), Obj, FieldID, V) :- 708 jGetObjectField(Obj, FieldID, V).
length(Array)
; HiIndex is an integer, LoIndex-1 =< HiIndex <
length(Array)
; at call, Vcs will be unbound; at exit, Vcs will be a
list of (references to) the array's elements [LoIndex..HiIndex]
inclusive
720jpl_get_object_array_elements(Array, Lo, Hi, Vcs) :-
721 ( Lo =< Hi
722 -> Vcs = [Vc|Vcs2],
723 jGetObjectArrayElement(Array, Lo, Vc),
724 Next is Lo+1,
725 jpl_get_object_array_elements(Array, Next, Hi, Vcs2)
726 ; Vcs = []
727 ).
737jpl_get_primitive_array_elements(ElementType, Array, Lo, Hi, Vcs) :- 738 Size is Hi-Lo+1, 739 ( Size == 0 740 -> Vcs = [] 741 ; jni_type_to_xput_code(ElementType, Xc), 742 jni_alloc_buffer(Xc, Size, Bp), 743 jpl_get_primitive_array_region(ElementType, Array, Lo, Size, Bp), 744 jpl_primitive_buffer_to_array(ElementType, Xc, Bp, 0, Size, Vcs), 745 jni_free_buffer(Bp) 746 ). 747 748 749jpl_get_primitive_array_region(boolean, Array, Lo, S, I) :- 750 jGetBooleanArrayRegion(Array, Lo, S, jbuf(I,boolean)). 751jpl_get_primitive_array_region(byte, Array, Lo, S, I) :- 752 jGetByteArrayRegion(Array, Lo, S, jbuf(I,byte)). 753jpl_get_primitive_array_region(char, Array, Lo, S, I) :- 754 jGetCharArrayRegion(Array, Lo, S, jbuf(I,char)). 755jpl_get_primitive_array_region(short, Array, Lo, S, I) :- 756 jGetShortArrayRegion(Array, Lo, S, jbuf(I,short)). 757jpl_get_primitive_array_region(int, Array, Lo, S, I) :- 758 jGetIntArrayRegion(Array, Lo, S, jbuf(I,int)). 759jpl_get_primitive_array_region(long, Array, Lo, S, I) :- 760 jGetLongArrayRegion(Array, Lo, S, jbuf(I,long)). 761jpl_get_primitive_array_region(float, Array, Lo, S, I) :- 762 jGetFloatArrayRegion(Array, Lo, S, jbuf(I,float)). 763jpl_get_primitive_array_region(double, Array, Lo, S, I) :- 764 jGetDoubleArrayRegion(Array, Lo, S, jbuf(I,double)). 765 766 767jpl_get_static_field(boolean, Array, FieldID, V) :- 768 jGetStaticBooleanField(Array, FieldID, V). 769jpl_get_static_field(byte, Array, FieldID, V) :- 770 jGetStaticByteField(Array, FieldID, V). 771jpl_get_static_field(char, Array, FieldID, V) :- 772 jGetStaticCharField(Array, FieldID, V). 773jpl_get_static_field(short, Array, FieldID, V) :- 774 jGetStaticShortField(Array, FieldID, V). 775jpl_get_static_field(int, Array, FieldID, V) :- 776 jGetStaticIntField(Array, FieldID, V). 777jpl_get_static_field(long, Array, FieldID, V) :- 778 jGetStaticLongField(Array, FieldID, V). 779jpl_get_static_field(float, Array, FieldID, V) :- 780 jGetStaticFloatField(Array, FieldID, V). 781jpl_get_static_field(double, Array, FieldID, V) :- 782 jGetStaticDoubleField(Array, FieldID, V). 783jpl_get_static_field(class(_,_), Array, FieldID, V) :- 784 jGetStaticObjectField(Array, FieldID, V). 785jpl_get_static_field(array(_), Array, FieldID, V) :- 786 jGetStaticObjectField(Array, FieldID, V).
X can be
class(_,_)
or array(_)
type (for static fields)Fspec can be
V must be a suitable value or object.
806jpl_set(X, Fspec, V) :-
807 ( jpl_object_to_type(X, Type) % the usual case (test is safe if X is var or rubbish)
808 -> Obj = X,
809 catch(
810 jpl_set_instance(Type, Type, Obj, Fspec, V), % first 'Type' is for FAI
811 % 2020-07-21: make catcher's 1st context arg an "anonvar" instead of a overspecified predicate indicator
812 error(type_error(acyclic,Te),context(_,Msg)),
813 throwme(jpl_set,acyclic(Te,Msg)) % rethrow
814 )
815 ; var(X)
816 -> throwme(jpl_set,arg1_is_var)
817 ; ( atom(X)
818 -> ( jpl_entityname_to_type(X, Type) % it's a classname or descriptor...
819 -> true
820 ; throwme(jpl_set,classname_does_not_resolve(X))
821 )
822 ; ( X = class(_,_) % it's a class type...
823 ; X = array(_) % ...or an array type
824 )
825 -> Type = X
826 ),
827 ( jpl_type_to_class(Type, ClassObj) % ...whose Class object is available
828 -> true
829 ; throwme(jpl_set,named_class_not_found(Type))
830 )
831 -> catch(
832 jpl_set_static(Type, ClassObj, Fspec, V),
833 % 2020-07-21: make catcher's 1st context arg an "anonvar" instead of a overspecified predicate indicator
834 error(type_error(acyclic,Te),context(_,Msg)),
835 throwme(jpl_set,acyclic(Te,Msg)) % rethrow
836 )
837 ; throwme(jpl_set,arg1_is_bad(X))
838 ).
FieldName should name a public, non-final (static or non-static) field of this object, but could be anything, and is validated here;
Value should be assignable to the named field, but could be anything, and is validated here
851jpl_set_instance(class(_,_), Type, Obj, Fname, V) :- % a non-array object 852 ( atom(Fname) % the usual case 853 -> true 854 ; var(Fname) 855 -> throwme(jpl_set_instance_class,arg2_is_var) 856 ; throwme(jpl_set_instance_class,arg2_is_bad(Fname)) 857 ), 858 findall( 859 z4(I,Mods,FID,Tf), 860 jpl_field_spec(Type, I, Fname, Mods, FID, Tf), % public fields of class denoted by Type 861 Z4s 862 ), 863 ( Z4s = [] 864 -> throwme(jpl_set_instance_class,no_such_field(Fname)) 865 ; Z4s = [z4(I,Mods,FID,Tf)] 866 -> ( member(final, Mods) 867 -> throwme(jpl_set_instance_class,field_is_final(Fname)) 868 ; jpl_datum_to_type(V, Tv) 869 -> ( jpl_type_fits_type(Tv, Tf) 870 -> ( member(static, Mods) 871 -> jpl_object_to_class(Obj, ClassObj), 872 jpl_set_static_field(Tf, ClassObj, FID, V) 873 ; jpl_set_instance_field(Tf, Obj, FID, V) % oughta be jpl_set_instance_field? 874 ) 875 ; throwme(jpl_set_instance_class,incompatible_value(Tf,V)) 876 ) 877 ; throwme(jpl_set_instance_class,arg3_is_bad(V)) 878 ) 879 ; throwme(jpl_set_instance_class,multiple_fields(Fname)) % 'existence'? or some other sort of error maybe? 880 ). 881 882 883 884jpl_set_instance(array(Type), _, Obj, Fspec, V) :- 885 ( is_list(V) % a list of array element values 886 -> Vs = V 887 ; var(V) 888 -> throwme(jpl_set_instance_array,arg3_is_var) 889 ; Vs = [V] % a single array element value 890 ), 891 length(Vs, Iv), 892 ( var(Fspec) 893 -> throwme(jpl_set_instance_array,arg2_is_var) 894 ; integer(Fspec) % single-element assignment 895 -> ( Fspec < 0 896 -> throwme(jpl_set_instance_array,arg2_is_bad(Fspec)) 897 ; Iv is 1 898 -> N is Fspec 899 ; Iv is 0 900 -> throwme(jpl_set_instance_array,no_values(Fspec,Vs)) 901 ; throwme(jpl_set_instance_array,more_than_one_value(Fspec,Vs)) 902 ) 903 ; Fspec = N-M % element-sequence assignment 904 -> ( integer(N), 905 integer(M) 906 -> ( N >= 0, 907 Size is (M-N)+1, 908 Size >= 0 909 -> ( Size == Iv 910 -> true 911 ; Size < Iv 912 -> throwme(jpl_set_instance_array,too_few_values(N-M,Vs)) 913 ; throwme(jpl_set_instance_array,too_many_values(N-M,Vs)) 914 ) 915 ; throwme(jpl_set_instance_array,bad_range_pair_values(N-M)) 916 ) 917 ; throwme(jpl_set_instance_array,bad_range_pair_types(N-M)) 918 ) 919 ; atom(Fspec) 920 -> ( Fspec == length 921 -> throwme(jpl_set_instance_array,cannot_assign_to_final_field) 922 ; throwme(jpl_set_instance_array,no_such_field(Fspec)) 923 ) 924 ; throwme(jpl_set_instance_array,arg2_is_bad_2(Fspec)) 925 ), 926 jpl_set_array(Type, Obj, N, Iv, Vs).
NB this does not yet handle shadowed fields correctly.
941jpl_set_static(Type, ClassObj, Fname, V) :-
942 ( atom(Fname) % the usual case
943 -> true
944 ; var(Fname)
945 -> throwme(jpl_set_static,arg2_is_unbound)
946 ; throwme(jpl_set_static,arg2_is_bad(Fname))
947 ),
948 findall( % get all static fields of the denoted class
949 z4(I,Mods,FID,Tf),
950 ( jpl_field_spec(Type, I, Fname, Mods, FID, Tf),
951 member(static, Mods)
952 ),
953 Z4s
954 ),
955 ( Z4s = []
956 -> throwme(jpl_set_static,no_such_public_static_field(field,Fname))
957 ; Z4s = [z4(I,Mods,FID,Tf)] % exactly one synonymous field?
958 -> ( member(final, Mods)
959 -> throwme(jpl_set_static,cannot_assign_final_field(Fname))
960 ; jpl_datum_to_type(V, Tv)
961 -> ( jpl_type_fits_type(Tv, Tf)
962 -> jpl_set_static_field(Tf, ClassObj, FID, V)
963 ; throwme(jpl_set_static,value_not_assignable(Tf,V))
964 )
965 ; throwme(jpl_set_static,arg3_is_bad(field_value,V))
966 )
967 ; throwme(jpl_set_static,multiple_matches(field,Fname))
968 ).
error(type_error(acyclic,_),context(jpl_datum_to_type/2,_))
978jpl_set_array(T, A, N, I, Ds) :-
979 ( jpl_datums_to_types(Ds, Tds) % most specialised types of given values
980 -> ( jpl_types_fit_type(Tds, T) % all assignable to element type?
981 -> true
982 ; throwme(jpl_set_array,not_all_values_assignable(T,Ds))
983 )
984 ; throwme(jpl_set_array,not_all_values_convertible(T,Ds))
985 ),
986 ( ( T = class(_,_)
987 ; T = array(_) % array elements are objects
988 )
989 -> ( nth0(J, Ds, D), % for each datum
990 Nd is N+J, % compute array index
991 ( D = {Tq} % quoted term?
992 -> jni_term_to_jref(Tq, D2) % convert to a JPL reference to a corresponding org.jpl7.Term object
993 ; D = D2
994 ),
995 jSetObjectArrayElement(A, Nd, D2),
996 fail % iterate
997 ; true
998 )
999 ; jpl_primitive_type(T) % array elements are primitive values
1000 -> jni_type_to_xput_code(T, Xc),
1001 jni_alloc_buffer(Xc, I, Bp), % I-element buf of required primitive type
1002 jpl_set_array_1(Ds, T, 0, Bp),
1003 jpl_set_elements(T, A, N, I, Bp),
1004 jni_free_buffer(Bp)
1005 ;
1006 % T is neither a class, nor an array type nor a primitive type
1007 throwme(jpl_set_array,element_type_unknown(array_element_type,T))
1008 ).
NB this could be done more efficiently (?) within foreign code...
1019jpl_set_array_1([], _, _, _). 1020jpl_set_array_1([V|Vs], Tprim, Ib, Bp) :- 1021 jni_type_to_xput_code(Tprim, Xc), 1022 jni_stash_buffer_value(Bp, Ib, V, Xc), 1023 Ibnext is Ib+1, 1024 jpl_set_array_1(Vs, Tprim, Ibnext, Bp). 1025 1026 1027jpl_set_elements(boolean, Obj, N, I, Bp) :- 1028 jSetBooleanArrayRegion(Obj, N, I, jbuf(Bp,boolean)). 1029jpl_set_elements(char, Obj, N, I, Bp) :- 1030 jSetCharArrayRegion(Obj, N, I, jbuf(Bp,char)). 1031jpl_set_elements(byte, Obj, N, I, Bp) :- 1032 jSetByteArrayRegion(Obj, N, I, jbuf(Bp,byte)). 1033jpl_set_elements(short, Obj, N, I, Bp) :- 1034 jSetShortArrayRegion(Obj, N, I, jbuf(Bp,short)). 1035jpl_set_elements(int, Obj, N, I, Bp) :- 1036 jSetIntArrayRegion(Obj, N, I, jbuf(Bp,int)). 1037jpl_set_elements(long, Obj, N, I, Bp) :- 1038 jSetLongArrayRegion(Obj, N, I, jbuf(Bp,long)). 1039jpl_set_elements(float, Obj, N, I, Bp) :- 1040 jSetFloatArrayRegion(Obj, N, I, jbuf(Bp,float)). 1041jpl_set_elements(double, Obj, N, I, Bp) :- 1042 jSetDoubleArrayRegion(Obj, N, I, jbuf(Bp,double)).
1050jpl_set_instance_field(boolean, Obj, FieldID, V) :- 1051 jSetBooleanField(Obj, FieldID, V). 1052jpl_set_instance_field(byte, Obj, FieldID, V) :- 1053 jSetByteField(Obj, FieldID, V). 1054jpl_set_instance_field(char, Obj, FieldID, V) :- 1055 jSetCharField(Obj, FieldID, V). 1056jpl_set_instance_field(short, Obj, FieldID, V) :- 1057 jSetShortField(Obj, FieldID, V). 1058jpl_set_instance_field(int, Obj, FieldID, V) :- 1059 jSetIntField(Obj, FieldID, V). 1060jpl_set_instance_field(long, Obj, FieldID, V) :- 1061 jSetLongField(Obj, FieldID, V). 1062jpl_set_instance_field(float, Obj, FieldID, V) :- 1063 jSetFloatField(Obj, FieldID, V). 1064jpl_set_instance_field(double, Obj, FieldID, V) :- 1065 jSetDoubleField(Obj, FieldID, V). 1066jpl_set_instance_field(class(_,_), Obj, FieldID, V) :- % also handles byval term assignments 1067 ( V = {T} % quoted term? 1068 -> jni_term_to_jref(T, V2) % convert to a JPL reference to a corresponding org.jpl7.Term object 1069 ; V = V2 1070 ), 1071 jSetObjectField(Obj, FieldID, V2). 1072jpl_set_instance_field(array(_), Obj, FieldID, V) :- 1073 jSetObjectField(Obj, FieldID, V).
1081jpl_set_static_field(boolean, Obj, FieldID, V) :- 1082 jSetStaticBooleanField(Obj, FieldID, V). 1083jpl_set_static_field(byte, Obj, FieldID, V) :- 1084 jSetStaticByteField(Obj, FieldID, V). 1085jpl_set_static_field(char, Obj, FieldID, V) :- 1086 jSetStaticCharField(Obj, FieldID, V). 1087jpl_set_static_field(short, Obj, FieldID, V) :- 1088 jSetStaticShortField(Obj, FieldID, V). 1089jpl_set_static_field(int, Obj, FieldID, V) :- 1090 jSetStaticIntField(Obj, FieldID, V). 1091jpl_set_static_field(long, Obj, FieldID, V) :- 1092 jSetStaticLongField(Obj, FieldID, V). 1093jpl_set_static_field(float, Obj, FieldID, V) :- 1094 jSetStaticFloatField(Obj, FieldID, V). 1095jpl_set_static_field(double, Obj, FieldID, V) :- 1096 jSetStaticDoubleField(Obj, FieldID, V). 1097jpl_set_static_field(class(_,_), Obj, FieldID, V) :- % also handles byval term assignments 1098 ( V = {T} % quoted term? 1099 -> jni_term_to_jref(T, V2) % convert to a JPL reference to a corresponding org.jpl7.Term object 1100 ; V = V2 1101 ), 1102 jSetStaticObjectField(Obj, FieldID, V2). 1103jpl_set_static_field(array(_), Obj, FieldID, V) :- 1104 jSetStaticObjectField(Obj, FieldID, V).
['-Xrs']
1112jpl_get_default_jvm_opts(Opts) :-
1113 jni_get_default_jvm_opts(Opts).
1120jpl_set_default_jvm_opts(Opts) :-
1121 is_list(Opts),
1122 length(Opts, N),
1123 jni_set_default_jvm_opts(N, Opts).
Fails silently if a JVM has not yet been started, and can thus be used to test for this.
1132jpl_get_actual_jvm_opts(Opts) :- 1133 jni_get_actual_jvm_opts(Opts). 1134 1135% =========================================================================== 1136% Caching 1137% =========================================================================== 1138 1139% In principle the predicates subject to assert/1 must be declared with the 1140% dynamic/1 directive. However, they are automatically declared as "dynamic" 1141% if they appear in an assert/1 call first. Anyway, we declare then dynamic 1142% right here! 1143 1144:- dynamic jpl_field_spec_cache/6. % document this... 1145:- dynamic jpl_field_spec_is_cached/1. % document this... 1146:- dynamic jpl_method_spec_cache/8. 1147:- dynamic jpl_method_spec_is_cached/1. 1148:- dynamic jpl_iref_type_cache/2.
NB may denote a class which cannot be found.
1156:- dynamic jpl_classname_type_cache/2.
java.lang.Class
which denotes Type.
We index on Class (a jref) so as to keep these objects around even after an atom garbage collection (if needed once, they are likely to be needed again)
(Is it possble to have different Ref for the same ClassType, which happens once several ClassLoaders become involved?) (Most likely)
1170:- dynamic jpl_class_tag_type_cache/2.
From the SWI-Prolog manual:
"In SWI-Prolog, querying dynamic predicates has the same performance as static ones. The manipulation predicates are fast."
And:
"By default, a predicate declared dynamic (see dynamic/1) is shared by all threads. Each thread may assert, retract and run the dynamic predicate. Synchronisation inside Prolog guarantees the consistency of the predicate. Updates are logical: visible clauses are not affected by assert/retract after a query started on the predicate. In many cases primitives from section 10.4 should be used to ensure that application invariants on the predicate are maintained.
1195jpl_assert(Fact) :- 1196 ( jpl_assert_policy(Fact, yes) 1197 -> assertz(Fact) 1198 ; true 1199 ). 1200 1201% --- 1202% policies 1203% --- 1204 1205jpl_assert_policy(jpl_field_spec_cache(_,_,_,_,_,_), yes). 1206jpl_assert_policy(jpl_field_spec_is_cached(_), YN) :- 1207 jpl_assert_policy(jpl_field_spec_cache(_,_,_,_,_,_), YN). 1208 1209jpl_assert_policy(jpl_method_spec_cache(_,_,_,_,_,_,_,_), yes). 1210jpl_assert_policy(jpl_method_spec_is_cached(_), YN) :- 1211 jpl_assert_policy(jpl_method_spec_cache(_,_,_,_,_,_,_,_), YN). 1212 1213jpl_assert_policy(jpl_class_tag_type_cache(_,_), yes). 1214jpl_assert_policy(jpl_classname_type_cache(_,_), yes). 1215jpl_assert_policy(jpl_iref_type_cache(_,_), no). % must correspond to JPL_CACHE_TYPE_OF_REF in jpl.c
Called from jpl.c's jni_free_iref()
via jni_tidy_iref_type_cache()
1223jpl_tidy_iref_type_cache(Iref) :- 1224 % write('[decaching types for iref='), write(Iref), write(']'), nl, 1225 retractall(jpl_iref_type_cache(Iref,_)), 1226 true. 1227 1228jpl_fergus_find_candidate([], Candidate, Candidate, []). 1229jpl_fergus_find_candidate([X|Xs], Candidate0, Candidate, Rest) :- 1230 ( jpl_fergus_greater(X, Candidate0) 1231 -> Candidate1 = X, 1232 Rest = [Candidate0|Rest1] 1233 ; Candidate1 = Candidate0, 1234 Rest = [X|Rest1] 1235 ), 1236 jpl_fergus_find_candidate(Xs, Candidate1, Candidate, Rest1). 1237 1238 1239jpl_fergus_greater(z5(_,_,_,_,Tps1), z5(_,_,_,_,Tps2)) :- 1240 jpl_types_fit_types(Tps1, Tps2). 1241jpl_fergus_greater(z3(_,_,Tps1), z3(_,_,Tps2)) :- 1242 jpl_types_fit_types(Tps1, Tps2).
1253jpl_fergus_is_the_greatest([X|Xs], Greatest) :-
1254 jpl_fergus_find_candidate(Xs, X, Greatest, Rest),
1255 forall(
1256 member(R, Rest),
1257 jpl_fergus_greater(Greatest, R)
1258 ).
z3(I,MID,Tfps)
.
Z is the single most specific element of Zs, i.e. that than which no other z3/3 has a more specialised signature (fails if there is more than one such).
1268jpl_z3s_to_most_specific_z3(Zs, Z) :-
1269 jpl_fergus_is_the_greatest(Zs, Z).
z5(I,Mods,MID,Tr,Tfps)
Z is the single most specific element of Zs, i.e. that than which no other z5/5 has a more specialised signature (fails if there is more than one such)
1279jpl_z5s_to_most_specific_z5(Zs, Z) :-
1280 jpl_fergus_is_the_greatest(Zs, Z).
jpl.pl
) of JPL.
It should exactly match the version identifiers of JPL's C (jpl.c) and Java (jpl.jar) components.
Example
?- jpl_pl_lib_version(V). V = '7.6.1'.
1296jpl_pl_lib_version(VersionString) :-
1297 jpl_pl_lib_version(Major, Minor, Patch, Status),
1298 atomic_list_concat([Major,'.',Minor,'.',Patch,'-',Status], VersionString).
Example
?- jpl:jpl_pl_lib_version(Major, Minor, Patch, Status). Major = 7, Minor = 4, Patch = 0, Status = alpha.
1315jpl_pl_lib_version(7, 6, 1, stable). % jref as blob
It should exactly match the version identifiers of JPL's Prolog (jpl.pl
) and Java (jpl.jar) components.
Example
?- jpl_c_lib_version(V). V = '7.4.0-alpha'.
Example
?- jpl:jpl_java_lib_version(V). V = '7.4.0-alpha'.
1344jpl_java_lib_version(V) :-
1345 jpl_call('org.jpl7.JPL', version_string, [], V).
1350jpl_pl_lib_path(Path) :-
1351 module_property(jpl, file(Path)).
1356jpl_c_lib_path(Path) :-
1357 shlib:current_library(_, _, Path, jpl, _),
1358 !.
1363jpl_java_lib_path(Path) :-
1364 jpl_call('org.jpl7.JPL', jarPath, [], Path).
1369jCallBooleanMethod(Obj, MethodID, Types, Params, Rbool) :-
1370 jni_params_put(Params, Types, ParamBuf),
1371 jni_func(39, Obj, MethodID, ParamBuf, Rbool).
1377jCallByteMethod(Obj, MethodID, Types, Params, Rbyte) :-
1378 jni_params_put(Params, Types, ParamBuf),
1379 jni_func(42, Obj, MethodID, ParamBuf, Rbyte).
1385jCallCharMethod(Obj, MethodID, Types, Params, Rchar) :-
1386 jni_params_put(Params, Types, ParamBuf),
1387 jni_func(45, Obj, MethodID, ParamBuf, Rchar).
1392jCallDoubleMethod(Obj, MethodID, Types, Params, Rdouble) :-
1393 jni_params_put(Params, Types, ParamBuf),
1394 jni_func(60, Obj, MethodID, ParamBuf, Rdouble).
1399jCallFloatMethod(Obj, MethodID, Types, Params, Rfloat) :-
1400 jni_params_put(Params, Types, ParamBuf),
1401 jni_func(57, Obj, MethodID, ParamBuf, Rfloat).
1406jCallIntMethod(Obj, MethodID, Types, Params, Rint) :-
1407 jni_params_put(Params, Types, ParamBuf),
1408 jni_func(51, Obj, MethodID, ParamBuf, Rint).
1413jCallLongMethod(Obj, MethodID, Types, Params, Rlong) :-
1414 jni_params_put(Params, Types, ParamBuf),
1415 jni_func(54, Obj, MethodID, ParamBuf, Rlong).
1420jCallObjectMethod(Obj, MethodID, Types, Params, Robj) :-
1421 jni_params_put(Params, Types, ParamBuf),
1422 jni_func(36, Obj, MethodID, ParamBuf, Robj).
1427jCallShortMethod(Obj, MethodID, Types, Params, Rshort) :-
1428 jni_params_put(Params, Types, ParamBuf),
1429 jni_func(48, Obj, MethodID, ParamBuf, Rshort).
1434jCallStaticBooleanMethod(Class, MethodID, Types, Params, Rbool) :-
1435 jni_params_put(Params, Types, ParamBuf),
1436 jni_func(119, Class, MethodID, ParamBuf, Rbool).
1441jCallStaticByteMethod(Class, MethodID, Types, Params, Rbyte) :-
1442 jni_params_put(Params, Types, ParamBuf),
1443 jni_func(122, Class, MethodID, ParamBuf, Rbyte).
1448jCallStaticCharMethod(Class, MethodID, Types, Params, Rchar) :-
1449 jni_params_put(Params, Types, ParamBuf),
1450 jni_func(125, Class, MethodID, ParamBuf, Rchar).
1455jCallStaticDoubleMethod(Class, MethodID, Types, Params, Rdouble) :-
1456 jni_params_put(Params, Types, ParamBuf),
1457 jni_func(140, Class, MethodID, ParamBuf, Rdouble).
1462jCallStaticFloatMethod(Class, MethodID, Types, Params, Rfloat) :-
1463 jni_params_put(Params, Types, ParamBuf),
1464 jni_func(137, Class, MethodID, ParamBuf, Rfloat).
1469jCallStaticIntMethod(Class, MethodID, Types, Params, Rint) :-
1470 jni_params_put(Params, Types, ParamBuf),
1471 jni_func(131, Class, MethodID, ParamBuf, Rint).
1476jCallStaticLongMethod(Class, MethodID, Types, Params, Rlong) :-
1477 jni_params_put(Params, Types, ParamBuf),
1478 jni_func(134, Class, MethodID, ParamBuf, Rlong).
1483jCallStaticObjectMethod(Class, MethodID, Types, Params, Robj) :-
1484 jni_params_put(Params, Types, ParamBuf),
1485 jni_func(116, Class, MethodID, ParamBuf, Robj).
1490jCallStaticShortMethod(Class, MethodID, Types, Params, Rshort) :-
1491 jni_params_put(Params, Types, ParamBuf),
1492 jni_func(128, Class, MethodID, ParamBuf, Rshort).
1497jCallStaticVoidMethod(Class, MethodID, Types, Params) :-
1498 jni_params_put(Params, Types, ParamBuf),
1499 jni_void(143, Class, MethodID, ParamBuf).
1504jCallVoidMethod(Obj, MethodID, Types, Params) :-
1505 jni_params_put(Params, Types, ParamBuf),
1506 jni_void(63, Obj, MethodID, ParamBuf).
1511jFindClass(ClassName, Class) :-
1512 jni_func(6, ClassName, Class).
1517jGetArrayLength(Array, Size) :-
1518 jni_func(171, Array, Size).
1523jGetBooleanArrayRegion(Array, Start, Len, Buf) :-
1524 jni_void(199, Array, Start, Len, Buf).
1529jGetBooleanField(Obj, FieldID, Rbool) :-
1530 jni_func(96, Obj, FieldID, Rbool).
1535jGetByteArrayRegion(Array, Start, Len, Buf) :-
1536 jni_void(200, Array, Start, Len, Buf).
1541jGetByteField(Obj, FieldID, Rbyte) :-
1542 jni_func(97, Obj, FieldID, Rbyte).
1547jGetCharArrayRegion(Array, Start, Len, Buf) :-
1548 jni_void(201, Array, Start, Len, Buf).
1553jGetCharField(Obj, FieldID, Rchar) :-
1554 jni_func(98, Obj, FieldID, Rchar).
1559jGetDoubleArrayRegion(Array, Start, Len, Buf) :-
1560 jni_void(206, Array, Start, Len, Buf).
1565jGetDoubleField(Obj, FieldID, Rdouble) :-
1566 jni_func(103, Obj, FieldID, Rdouble).
1571jGetFieldID(Class, Name, Type, FieldID) :-
1572 jpl_type_to_java_field_descriptor(Type, FD),
1573 jni_func(94, Class, Name, FD, FieldID).
1578jGetFloatArrayRegion(Array, Start, Len, Buf) :-
1579 jni_void(205, Array, Start, Len, Buf).
1584jGetFloatField(Obj, FieldID, Rfloat) :-
1585 jni_func(102, Obj, FieldID, Rfloat).
1590jGetIntArrayRegion(Array, Start, Len, Buf) :-
1591 jni_void(203, Array, Start, Len, Buf).
1596jGetIntField(Obj, FieldID, Rint) :-
1597 jni_func(100, Obj, FieldID, Rint).
1602jGetLongArrayRegion(Array, Start, Len, Buf) :-
1603 jni_void(204, Array, Start, Len, Buf).
1608jGetLongField(Obj, FieldID, Rlong) :-
1609 jni_func(101, Obj, FieldID, Rlong).
1614jGetMethodID(Class, Name, Type, MethodID) :-
1615 jpl_type_to_java_method_descriptor(Type, MD),
1616 jni_func(33, Class, Name, MD, MethodID).
1621jGetObjectArrayElement(Array, Index, Obj) :-
1622 jni_func(173, Array, Index, Obj).
1627jGetObjectClass(Object, Class) :-
1628 jni_func(31, Object, Class).
1633jGetObjectField(Obj, FieldID, Robj) :-
1634 jni_func(95, Obj, FieldID, Robj).
1639jGetShortArrayRegion(Array, Start, Len, Buf) :-
1640 jni_void(202, Array, Start, Len, Buf).
1645jGetShortField(Obj, FieldID, Rshort) :-
1646 jni_func(99, Obj, FieldID, Rshort).
1651jGetStaticBooleanField(Class, FieldID, Rbool) :-
1652 jni_func(146, Class, FieldID, Rbool).
1657jGetStaticByteField(Class, FieldID, Rbyte) :-
1658 jni_func(147, Class, FieldID, Rbyte).
1663jGetStaticCharField(Class, FieldID, Rchar) :-
1664 jni_func(148, Class, FieldID, Rchar).
1669jGetStaticDoubleField(Class, FieldID, Rdouble) :-
1670 jni_func(153, Class, FieldID, Rdouble).
1675jGetStaticFieldID(Class, Name, Type, FieldID) :-
1676 jpl_type_to_java_field_descriptor(Type, TD), % cache this?
1677 jni_func(144, Class, Name, TD, FieldID).
1682jGetStaticFloatField(Class, FieldID, Rfloat) :-
1683 jni_func(152, Class, FieldID, Rfloat).
1688jGetStaticIntField(Class, FieldID, Rint) :-
1689 jni_func(150, Class, FieldID, Rint).
1694jGetStaticLongField(Class, FieldID, Rlong) :-
1695 jni_func(151, Class, FieldID, Rlong).
1700jGetStaticMethodID(Class, Name, Type, MethodID) :-
1701 jpl_type_to_java_method_descriptor(Type, TD),
1702 jni_func(113, Class, Name, TD, MethodID).
1707jGetStaticObjectField(Class, FieldID, Robj) :-
1708 jni_func(145, Class, FieldID, Robj).
1713jGetStaticShortField(Class, FieldID, Rshort) :-
1714 jni_func(149, Class, FieldID, Rshort).
1719jGetSuperclass(Class1, Class2) :-
1720 jni_func(10, Class1, Class2).
1725jIsAssignableFrom(Class1, Class2) :-
1726 jni_func(11, Class1, Class2, @(true)).
1731jNewBooleanArray(Length, Array) :-
1732 jni_func(175, Length, Array).
1737jNewByteArray(Length, Array) :-
1738 jni_func(176, Length, Array).
1743jNewCharArray(Length, Array) :-
1744 jni_func(177, Length, Array).
1749jNewDoubleArray(Length, Array) :-
1750 jni_func(182, Length, Array).
1755jNewFloatArray(Length, Array) :-
1756 jni_func(181, Length, Array).
1761jNewIntArray(Length, Array) :-
1762 jni_func(179, Length, Array).
1767jNewLongArray(Length, Array) :-
1768 jni_func(180, Length, Array).
1773jNewObject(Class, MethodID, Types, Params, Obj) :-
1774 jni_params_put(Params, Types, ParamBuf),
1775 jni_func(30, Class, MethodID, ParamBuf, Obj).
1780jNewObjectArray(Len, Class, InitVal, Array) :-
1781 jni_func(172, Len, Class, InitVal, Array).
1786jNewShortArray(Length, Array) :-
1787 jni_func(178, Length, Array).
1792jSetBooleanArrayRegion(Array, Start, Len, Buf) :-
1793 jni_void(207, Array, Start, Len, Buf).
1798jSetBooleanField(Obj, FieldID, Rbool) :-
1799 jni_void(105, Obj, FieldID, Rbool).
1804jSetByteArrayRegion(Array, Start, Len, Buf) :-
1805 jni_void(208, Array, Start, Len, Buf).
1810jSetByteField(Obj, FieldID, Rbyte) :-
1811 jni_void(106, Obj, FieldID, Rbyte).
1816jSetCharArrayRegion(Array, Start, Len, Buf) :-
1817 jni_void(209, Array, Start, Len, Buf).
1822jSetCharField(Obj, FieldID, Rchar) :-
1823 jni_void(107, Obj, FieldID, Rchar).
1828jSetDoubleArrayRegion(Array, Start, Len, Buf) :-
1829 jni_void(214, Array, Start, Len, Buf).
1834jSetDoubleField(Obj, FieldID, Rdouble) :-
1835 jni_void(112, Obj, FieldID, Rdouble).
1840jSetFloatArrayRegion(Array, Start, Len, Buf) :-
1841 jni_void(213, Array, Start, Len, Buf).
1846jSetFloatField(Obj, FieldID, Rfloat) :-
1847 jni_void(111, Obj, FieldID, Rfloat).
1852jSetIntArrayRegion(Array, Start, Len, Buf) :-
1853 jni_void(211, Array, Start, Len, Buf).
1858jSetIntField(Obj, FieldID, Rint) :-
1859 jni_void(109, Obj, FieldID, Rint).
1864jSetLongArrayRegion(Array, Start, Len, Buf) :-
1865 jni_void(212, Array, Start, Len, Buf).
1870jSetLongField(Obj, FieldID, Rlong) :-
1871 jni_void(110, Obj, FieldID, Rlong).
1876jSetObjectArrayElement(Array, Index, Obj) :-
1877 jni_void(174, Array, Index, Obj).
1882jSetObjectField(Obj, FieldID, Robj) :-
1883 jni_void(104, Obj, FieldID, Robj).
1888jSetShortArrayRegion(Array, Start, Len, Buf) :-
1889 jni_void(210, Array, Start, Len, Buf).
1894jSetShortField(Obj, FieldID, Rshort) :-
1895 jni_void(108, Obj, FieldID, Rshort).
1900jSetStaticBooleanField(Class, FieldID, Rbool) :-
1901 jni_void(155, Class, FieldID, Rbool).
1906jSetStaticByteField(Class, FieldID, Rbyte) :-
1907 jni_void(156, Class, FieldID, Rbyte).
1912jSetStaticCharField(Class, FieldID, Rchar) :-
1913 jni_void(157, Class, FieldID, Rchar).
1918jSetStaticDoubleField(Class, FieldID, Rdouble) :-
1919 jni_void(162, Class, FieldID, Rdouble).
1924jSetStaticFloatField(Class, FieldID, Rfloat) :-
1925 jni_void(161, Class, FieldID, Rfloat).
1930jSetStaticIntField(Class, FieldID, Rint) :-
1931 jni_void(159, Class, FieldID, Rint).
1936jSetStaticLongField(Class, FieldID, Rlong) :-
1937 jni_void(160, Class, FieldID, Rlong).
1942jSetStaticObjectField(Class, FieldID, Robj) :-
1943 jni_void(154, Class, FieldID, Robj).
1948jSetStaticShortField(Class, FieldID, Rshort) :-
1949 jni_void(158, Class, FieldID, Rshort).
1959jni_params_put(As, Ts, ParamBuf) :-
1960 jni_ensure_jvm, % in case e.g. NewStringUTF() is called
1961 length(As, N),
1962 jni_type_to_xput_code(jvalue, Xc), % Xc will be 15
1963 jni_alloc_buffer(Xc, N, ParamBuf),
1964 jni_params_put_1(As, 0, Ts, ParamBuf).
Types are their (JPL) types (e.g. 'boolean').
N is the arg and buffer index (0+) at which the head of Params is to be stashed.
The old form used a static buffer and hence was non-reentrant; the new form uses a dynamically allocated buffer (which oughta be freed after use).
NB if the (user-provided) actual params were to be unsuitable for conversion to the method-required types, this would fail silently (without freeing the buffer); it's not clear whether the overloaded-method-resolution ensures that all args are convertible
1983jni_params_put_1([], _, [], _). 1984jni_params_put_1([A|As], N, [Tjni|Ts], ParamBuf) :- % type checking? 1985 ( jni_type_to_xput_code(Tjni, Xc) 1986 -> ( A = {Term} % a quoted general term? 1987 -> jni_term_to_jref(Term, Ax) % convert it to a @(Tag) ref to a new Term instance 1988 ; A = Ax 1989 ), 1990 jni_param_put(N, Xc, Ax, ParamBuf) % foreign 1991 ; fail % oughta raise an exception? 1992 ), 1993 N2 is N+1, 1994 jni_params_put_1(As, N2, Ts, ParamBuf). % stash remaining params (if any)
NB the codes could be compiled into jni_method_spec_cache etc. instead of, or as well as, types (for - small - efficiency gain)
2004jni_type_to_xput_code(boolean, 1). % JNI_XPUT_BOOLEAN 2005jni_type_to_xput_code(byte, 2). % JNI_XPUT_BYTE 2006jni_type_to_xput_code(char, 3). % JNI_XPUT_CHAR 2007jni_type_to_xput_code(short, 4). % JNI_XPUT_SHORT 2008jni_type_to_xput_code(int, 5). % JNI_XPUT_INT 2009jni_type_to_xput_code(long, 6). % JNI_XPUT_LONG 2010jni_type_to_xput_code(float, 7). % JNI_XPUT_FLOAT 2011jni_type_to_xput_code(double, 8). % JNI_XPUT_DOUBLE 2012jni_type_to_xput_code(class(_,_), 12). % JNI_XPUT_REF 2013jni_type_to_xput_code(array(_), 12). % JNI_XPUT_REF 2014jni_type_to_xput_code(jvalue, 15). % JNI_XPUT_JVALUE
2021jpl_class_to_constructor_array(Cx, Ma) :-
2022 jpl_entityname_to_class('java.lang.Class', CC), % cacheable?
2023 jGetMethodID( CC, getConstructors, method([],array(class([java,lang,reflect],['Constructor']))), MID), % cacheable?
2024 jCallObjectMethod(Cx, MID, [], [], Ma).
2029jpl_class_to_constructors(Cx, Ms) :-
2030 jpl_class_to_constructor_array(Cx, Ma),
2031 jpl_object_array_to_list(Ma, Ms).
2036jpl_class_to_field_array(Cx, Fa) :-
2037 jpl_entityname_to_class('java.lang.Class', CC), % cacheable?
2038 jGetMethodID(CC, getFields, method([],array(class([java,lang,reflect],['Field']))), MID), % cacheable?
2039 jCallObjectMethod(Cx, MID, [], [], Fa).
2046jpl_class_to_fields(C, Fs) :-
2047 jpl_class_to_field_array(C, Fa),
2048 jpl_object_array_to_list(Fa, Fs).
2055jpl_class_to_method_array(Cx, Ma) :-
2056 jpl_entityname_to_class('java.lang.Class', CC), % cacheable?
2057 jGetMethodID(CC, getMethods, method([],array(class([java,lang,reflect],['Method']))), MID), % cacheable?
2058 jCallObjectMethod(Cx, MID, [], [], Ma).
NB do this in Java (ditto for fields)?
2067jpl_class_to_methods(Cx, Ms) :-
2068 jpl_class_to_method_array(Cx, Ma),
2069 jpl_object_array_to_list(Ma, Ms).
2076jpl_constructor_to_modifiers(X, Ms) :-
2077 jpl_entityname_to_class('java.lang.reflect.Constructor', Cx), % cached?
2078 jpl_method_to_modifiers_1(X, Cx, Ms).
2086jpl_constructor_to_name(_X, '<init>').
2093jpl_constructor_to_parameter_types(X, Tfps) :-
2094 jpl_entityname_to_class('java.lang.reflect.Constructor', Cx), % cached?
2095 jpl_method_to_parameter_types_1(X, Cx, Tfps).
2103jpl_constructor_to_return_type(_X, void).
2110jpl_field_spec(T, I, N, Mods, MID, Tf) :- 2111 ( jpl_field_spec_is_cached(T) 2112 -> jpl_field_spec_cache(T, I, N, Mods, MID, Tf) 2113 ; jpl_type_to_class(T, C), 2114 jpl_class_to_fields(C, Fs), 2115 ( T = array(_BaseType) % regardless of base type... 2116 -> Tci = array(_) % ...the "cache index" type is this 2117 ; Tci = T 2118 ), 2119 jpl_field_spec_1(C, Tci, Fs), 2120 jpl_assert(jpl_field_spec_is_cached(Tci)), 2121 jpl_field_spec_cache(Tci, I, N, Mods, MID, Tf) 2122 ). 2123 2124 2125jpl_field_spec_1(C, Tci, Fs) :- 2126 ( nth1(I, Fs, F), 2127 jpl_field_to_name(F, N), 2128 jpl_field_to_modifiers(F, Mods), 2129 jpl_field_to_type(F, Tf), 2130 ( member(static, Mods) 2131 -> jGetStaticFieldID(C, N, Tf, MID) 2132 ; jGetFieldID(C, N, Tf, MID) 2133 ), 2134 jpl_assert(jpl_field_spec_cache(Tci,I,N,Mods,MID,Tf)), 2135 fail 2136 ; true 2137 ).
2143jpl_field_to_modifiers(F, Ms) :-
2144 jpl_entityname_to_class('java.lang.reflect.Field', Cf),
2145 jpl_method_to_modifiers_1(F, Cf, Ms).
2150jpl_field_to_name(F, N) :-
2151 jpl_entityname_to_class('java.lang.reflect.Field', Cf),
2152 jpl_member_to_name_1(F, Cf, N).
2157jpl_field_to_type(F, Tf) :-
2158 jpl_entityname_to_class('java.lang.reflect.Field', Cf),
2159 jGetMethodID(Cf, getType, method([],class([java,lang],['Class'])), MID),
2160 jCallObjectMethod(F, MID, [], [], Cr),
2161 jpl_class_to_type(Cr, Tf).
2169jpl_method_spec(T, I, N, A, Mods, MID, Tr, Tfps) :-
2170 ( jpl_method_spec_is_cached(T)
2171 -> jpl_method_spec_cache(T, I, N, A, Mods, MID, Tr, Tfps)
2172 ; jpl_type_to_class(T, C),
2173 jpl_class_to_constructors(C, Xs),
2174 jpl_class_to_methods(C, Ms),
2175 ( T = array(_BaseType) % regardless of base type...
2176 -> Tci = array(_) % ...the "cache index" type is this
2177 ; Tci = T
2178 ),
2179 jpl_method_spec_1(C, Tci, Xs, Ms),
2180 jpl_assert(jpl_method_spec_is_cached(Tci)),
2181 jpl_method_spec_cache(Tci, I, N, A, Mods, MID, Tr, Tfps)
2182 ).
array(byte)
then CacheIndexType is array(_)
else it is that type.
2189jpl_method_spec_1(C, Tci, Xs, Ms) :-
2190 ( ( nth1(I, Xs, X), % generate constructors, numbered from 1
2191 jpl_constructor_to_name(X, N),
2192 jpl_constructor_to_modifiers(X, Mods),
2193 jpl_constructor_to_return_type(X, Tr),
2194 jpl_constructor_to_parameter_types(X, Tfps)
2195 ; length(Xs, J0),
2196 nth1(J, Ms, M), % generate members, continuing numbering
2197 I is J0+J,
2198 jpl_method_to_name(M, N),
2199 jpl_method_to_modifiers(M, Mods),
2200 jpl_method_to_return_type(M, Tr),
2201 jpl_method_to_parameter_types(M, Tfps)
2202 ),
2203 length(Tfps, A), % arity
2204 ( member(static, Mods)
2205 -> jGetStaticMethodID(C, N, method(Tfps,Tr), MID)
2206 ; jGetMethodID(C, N, method(Tfps,Tr), MID)
2207 ),
2208 jpl_assert(jpl_method_spec_cache(Tci,I,N,A,Mods,MID,Tr,Tfps)),
2209 fail
2210 ; true
2211 ).
2217jpl_method_to_modifiers(M, Ms) :-
2218 jpl_entityname_to_class('java.lang.reflect.Method', Cm),
2219 jpl_method_to_modifiers_1(M, Cm, Ms).
2224jpl_method_to_modifiers_1(XM, Cxm, Ms) :-
2225 jGetMethodID(Cxm, getModifiers, method([],int), MID),
2226 jCallIntMethod(XM, MID, [], [], I),
2227 jpl_modifier_int_to_modifiers(I, Ms).
2232jpl_method_to_name(M, N) :-
2233 jpl_entityname_to_class('java.lang.reflect.Method', CM),
2234 jpl_member_to_name_1(M, CM, N).
2239jpl_member_to_name_1(M, CM, N) :-
2240 jGetMethodID(CM, getName, method([],class([java,lang],['String'])), MID),
2241 jCallObjectMethod(M, MID, [], [], N).
2246jpl_method_to_parameter_types(M, Tfps) :-
2247 jpl_entityname_to_class('java.lang.reflect.Method', Cm),
2248 jpl_method_to_parameter_types_1(M, Cm, Tfps).
2255jpl_method_to_parameter_types_1(XM, Cxm, Tfps) :-
2256 jGetMethodID(Cxm, getParameterTypes, method([],array(class([java,lang],['Class']))), MID),
2257 jCallObjectMethod(XM, MID, [], [], Atp),
2258 jpl_object_array_to_list(Atp, Ctps),
2259 jpl_classes_to_types(Ctps, Tfps).
2264jpl_method_to_return_type(M, Tr) :- 2265 jpl_entityname_to_class('java.lang.reflect.Method', Cm), 2266 jGetMethodID(Cm, getReturnType, method([],class([java,lang],['Class'])), MID), 2267 jCallObjectMethod(M, MID, [], [], Cr), 2268 jpl_class_to_type(Cr, Tr). 2269 2270 2271jpl_modifier_bit(public, 0x001). 2272jpl_modifier_bit(private, 0x002). 2273jpl_modifier_bit(protected, 0x004). 2274jpl_modifier_bit(static, 0x008). 2275jpl_modifier_bit(final, 0x010). 2276jpl_modifier_bit(synchronized, 0x020). 2277jpl_modifier_bit(volatile, 0x040). 2278jpl_modifier_bit(transient, 0x080). 2279jpl_modifier_bit(native, 0x100). 2280jpl_modifier_bit(interface, 0x200). 2281jpl_modifier_bit(abstract, 0x400).
2290jpl_modifier_int_to_modifiers(I, Ms) :-
2291 setof(
2292 M, % should use e.g. set_of_all/3
2293 B^( jpl_modifier_bit(M, B),
2294 (B /\ I) =\= 0
2295 ),
2296 Ms
2297 ).
Ref must be a proper JPL reference (not void)
Type is memoed (if policy so dictates) as the type of the referenced object (unless it's null) by iref (so as not to disable atom-based GC)
NB obsolete lemmas must be watched-out-for and removed
2311jpl_cache_type_of_ref(T, Ref) :-
2312 ( jpl_assert_policy(jpl_iref_type_cache(_,_), no)
2313 -> true
2314 ; \+ ground(T) % shouldn't happen (implementation error)
2315 -> write('[jpl_cache_type_of_ref/2: arg 1 is not ground]'), nl, % oughta throw an exception
2316 fail
2317 ; Ref == @(null) % a null ref? (this is valid)
2318 -> true % silently ignore it
2319 ; ( jpl_iref_type_cache(Ref, TC) % we expect TC == T
2320 -> ( T == TC
2321 -> true
2322 ; % write('[JPL: found obsolete tag-type lemma...]'), nl, % or keep statistics? (why?)
2323 retractall(jpl_iref_type_cache(Ref,_)),
2324 jpl_assert(jpl_iref_type_cache(Ref,T))
2325 )
2326 ; jpl_assert(jpl_iref_type_cache(Ref,T))
2327 )
2328 ).
2339jpl_class_to_ancestor_classes(C, Cas) :-
2340 ( jpl_class_to_super_class(C, Ca)
2341 -> Cas = [Ca|Cas2],
2342 jpl_class_to_ancestor_classes(Ca, Cas2)
2343 ; Cas = []
2344 ).
ClassName is its canonical (?) source-syntax (dotted) name,
e.g. 'java.util.Date'
NB not used outside jni_junk and jpl_test (is this (still) true?)
NB oughta use the available caches (but their indexing doesn't suit)
TODO
This shouldn't exist as we have jpl_class_to_entityname/2 ???
The implementation actually just calls Class.getName()
to get
the entity name (dotted name)
2363jpl_class_to_classname(C, CN) :-
2364 jpl_call(C, getName, [], CN).
Class.getName()
.
This predicate actually calls Class.getName()
on the class corresponding to Class.
2376jpl_class_to_entityname(Class, EntityName) :- 2377 jpl_entityname_to_class('java.lang.Class', CC), % cached? 2378 jGetMethodID(CC, getName, method([],class([java,lang],['String'])), MIDgetName), % does this ever change? 2379 jCallObjectMethod(Class, MIDgetName, [], [], S), 2380 S = EntityName. 2381 2382 2383jpl_class_to_super_class(C, Cx) :- 2384 jGetSuperclass(C, Cx), 2385 Cx \== @(null), % as returned when C is java.lang.Object, i.e. no superclass 2386 jpl_cache_type_of_ref(class([java,lang],['Class']), Cx).
java.lang.Class
.
The Type is the (Prolog Universe) JPL type term denoting the same type as does
the instance of Class.
NB should ensure that, if not found in cache, then cache is updated.
Intriguingly, getParameterTypes returns class objects (undocumented AFAIK) with names 'boolean', 'byte' etc. and even 'void' (?!)
2400jpl_class_to_type(Class, Type) :- 2401 assertion(blob(Class,jref)), % "Class" cannot be uninstantiated and must be blob jref 2402 ( jpl_class_tag_type_cache(Class, Tx) % found in cache! 2403 -> true 2404 ; jpl_class_to_entityname(Class, EN), % uncached ?? 2405 jpl_entityname_to_type(EN, Tr), 2406 jpl_type_to_canonical_type(Tr, Tx), % map e.g. class([],[byte]) -> byte (TODO: Looks like a dirty fix; I would say this is not needed now) 2407 jpl_assert(jpl_class_tag_type_cache(Class,Tx)) 2408 -> true % the elseif goal should be determinate, but just in case... TODO: Replace by a once 2409 ), 2410 Type = Tx. 2411 2412 2413jpl_classes_to_types([], []). 2414jpl_classes_to_types([C|Cs], [T|Ts]) :- 2415 jpl_class_to_type(C, T), 2416 jpl_classes_to_types(Cs, Ts).
Class is a (canonical) reference to the corresponding class object.
NB uses caches where the class is already encountered.
2427jpl_entityname_to_class(EntityName, Class) :- 2428 jpl_entityname_to_type(EntityName, T), % cached 2429 jpl_type_to_class(T, Class). % cached
Class is a (canonical) reference to the corresponding class object.
NB uses caches where the class has already been mapped once before.
2439jpl_classname_to_class(EntityName, Class) :- 2440 jpl_entityname_to_class(EntityName, Class). % wrapper for historical usage/export 2441 2442% ========================================================= 2443% Java Entity Name (atom) <----> JPL Type (Prolog term) 2444% =========================================================
java.lang.Class.getName()
.
Type is the JPL type (a ground term) denoting the same Java type as EntityName does.
The Java type in question may be a reference type (class, abstract class, interface), and array type or a primitive, including "void".
Examples:
int int integer class([],[integer]) void void char char double double [D array(double) [[I array(array(int)) java.lang.String class([java,lang],['String']) [Ljava.lang.String; array(class([java,lang],['String'])) [[Ljava.lang.String; array(array(class([java, lang], ['String']))) [[[Ljava.util.Calendar; array(array(array(class([java,util],['Calendar'])))) foo.bar.Bling$Blong class([foo,bar],['Bling','Blong'])
NB uses caches where the class has already been mapped once before.
2479jpl_entityname_to_type(EntityName, Type) :- 2480 assertion(atomic(EntityName)), 2481 (jpl_classname_type_cache(EntityName, Tx) 2482 -> (Tx = Type) 2483 ; jpl_entityname_to_type_with_caching(EntityName, Type)). 2484 2485jpl_entityname_to_type_with_caching(EN, T) :- 2486 (atom_codes(EN,Cs),phrase(jpl_entityname(T), Cs)) 2487 -> jpl_assert(jpl_classname_type_cache(EN,T)).
2493jpl_type_to_entityname(Type, EntityName) :-
2494 assertion(ground(Type)),
2495 phrase(jpl_entityname(Type), Cs),
2496 atom_codes(EntityName, Cs).
Use jpl_entityname_to_type/2 in preference.
2507jpl_classname_to_type(EntityName, Type) :-
2508 jpl_entityname_to_type(EntityName, Type).
Use jpl_type_to_entityname/2 in preference.
2519% N.B. This predicate is exported, but internally it is only used to generate 2520% exception information. 2521 2522jpl_type_to_classname(Type, EntityName) :- 2523 jpl_type_to_entityname(Type, EntityName). 2524 2525% =========================================================
Type is the unique most specialised type of which Datum denotes an instance;
NB 3 is an instance of byte, char, short, int and long, of which byte and char are the joint, overlapping most specialised types, so this relates 3 to the pseudo subtype 'char_byte';
2540jpl_datum_to_type(D, T) :- 2541 ( jpl_value_to_type(D, T) 2542 -> true 2543 ; jpl_ref_to_type(D, T) 2544 -> true 2545 ; nonvar(D), 2546 D = {Term} 2547 -> ( cyclic_term(Term) 2548 -> throwme(jpl_datum_to_type,is_cyclic(Term)) 2549 ; atom(Term) 2550 -> T = class([org,jpl7],['Atom']) 2551 ; integer(Term) 2552 -> T = class([org,jpl7],['Integer']) 2553 ; float(Term) 2554 -> T = class([org,jpl7],['Float']) 2555 ; var(Term) 2556 -> T = class([org,jpl7],['Variable']) 2557 ; T = class([org,jpl7],['Compound']) 2558 ) 2559 ). 2560 2561 2562jpl_datums_to_most_specific_common_ancestor_type([D], T) :- 2563 jpl_datum_to_type(D, T). 2564jpl_datums_to_most_specific_common_ancestor_type([D1,D2|Ds], T0) :- 2565 jpl_datum_to_type(D1, T1), 2566 jpl_type_to_ancestor_types(T1, Ts1), 2567 jpl_datums_to_most_specific_common_ancestor_type_1([D2|Ds], [T1|Ts1], [T0|_]). 2568 2569 2570jpl_datums_to_most_specific_common_ancestor_type_1([], Ts, Ts). 2571jpl_datums_to_most_specific_common_ancestor_type_1([D|Ds], Ts1, Ts0) :- 2572 jpl_datum_to_type(D, Tx), 2573 jpl_lineage_types_type_to_common_lineage_types(Ts1, Tx, Ts2), 2574 jpl_datums_to_most_specific_common_ancestor_type_1(Ds, Ts2, Ts0).
2585jpl_datums_to_types([], []). 2586jpl_datums_to_types([D|Ds], [T|Ts]) :- 2587 jpl_datum_to_type(D, T), 2588 jpl_datums_to_types(Ds, Ts).
A (more complete) alternative would be to try to transfrom the X into its entityname and see whether that works.
2598jpl_ground_is_type(X) :- 2599 jpl_primitive_type(X), 2600 !. 2601jpl_ground_is_type(array(X)) :- 2602 jpl_ground_is_type(X). 2603jpl_ground_is_type(class(_,_)). % Should one check that the anonymous params are list of atoms, with the second list nonempty? 2604jpl_ground_is_type(method(_,_)). % Additional checks possible 2605 2606 2607 2608 2609jpl_lineage_types_type_to_common_lineage_types(Ts, Tx, Ts0) :- 2610 ( append(_, [Tx|Ts2], Ts) 2611 -> [Tx|Ts2] = Ts0 2612 ; jpl_type_to_super_type(Tx, Tx2) 2613 -> jpl_lineage_types_type_to_common_lineage_types(Ts, Tx2, Ts0) 2614 ). 2615 2616 2617jpl_non_var_is_object_type(class(_,_)). 2618 2619jpl_non_var_is_object_type(array(_)).
2627jpl_object_array_to_list(A, Vs) :-
2628 jpl_array_to_length(A, N),
2629 jpl_object_array_to_list_1(A, 0, N, Vs).
2634jpl_object_array_to_list_1(A, I, N, Xs) :-
2635 ( I == N
2636 -> Xs = []
2637 ; jGetObjectArrayElement(A, I, X),
2638 Xs = [X|Xs2],
2639 J is I+1,
2640 jpl_object_array_to_list_1(A, J, N, Xs2)
2641 ).
Class is a (canonical) reference to the (canonical) class object which represents the class of Object
NB what's the point of caching the type if we don't look there first?
2653jpl_object_to_class(Obj, C) :-
2654 jpl_is_object(Obj),
2655 jGetObjectClass(Obj, C),
2656 jpl_cache_type_of_ref(class([java,lang],['Class']), C).
Type is the JPL type of that object.
2666jpl_object_to_type(Ref, Type) :- 2667 jpl_is_object(Ref), 2668 ( jpl_iref_type_cache(Ref, T) 2669 -> true % T is Tag's type 2670 ; jpl_object_to_class(Ref, Cobj), % else get ref to class obj 2671 jpl_class_to_type(Cobj, T), % get type of class it denotes 2672 jpl_assert(jpl_iref_type_cache(Ref,T)) 2673 ), 2674 Type = T. 2675 2676 2677jpl_object_type_to_super_type(T, Tx) :- 2678 ( ( T = class(_,_) 2679 ; T = array(_) 2680 ) 2681 -> jpl_type_to_class(T, C), 2682 jpl_class_to_super_class(C, Cx), 2683 Cx \== @(null), 2684 jpl_class_to_type(Cx, Tx) 2685 ).
Vcs will be unbound on entry, and on exit will be a list of Size of them, starting at index I (the buffer is indexed from zero)
2696jpl_primitive_buffer_to_array(T, Xc, Bp, I, Size, [Vc|Vcs]) :-
2697 jni_fetch_buffer_value(Bp, I, Vc, Xc),
2698 Ix is I+1,
2699 ( Ix < Size
2700 -> jpl_primitive_buffer_to_array(T, Xc, Bp, Ix, Size, Vcs)
2701 ; Vcs = []
2702 ).
void
is not included.
?- setof(Type, jpl_primitive_type(Type), Types). Types = [boolean, byte, char, double, float, int, long, short].
2715jpl_primitive_type(boolean). 2716jpl_primitive_type(char). 2717jpl_primitive_type(byte). 2718jpl_primitive_type(short). 2719jpl_primitive_type(int). % N.B. "int" not "integer" 2720jpl_primitive_type(long). 2721jpl_primitive_type(float). 2722jpl_primitive_type(double).
2731jpl_primitive_type_default_value(boolean, @(false)). 2732jpl_primitive_type_default_value(char, 0). 2733jpl_primitive_type_default_value(byte, 0). 2734jpl_primitive_type_default_value(short, 0). 2735jpl_primitive_type_default_value(int, 0). 2736jpl_primitive_type_default_value(long, 0). 2737jpl_primitive_type_default_value(float, 0.0). 2738jpl_primitive_type_default_value(double, 0.0). 2739 2740 2741jpl_primitive_type_super_type(T, Tx) :- 2742 ( jpl_type_fits_type_direct_prim(T, Tx) 2743 ; jpl_type_fits_type_direct_xtra(T, Tx) 2744 ).
Val is the instance of Type which it represents (often the same thing).
NB currently used only by jpl_new_1 when creating an "instance" of a primitive type (which may be misguided completism - you can't do that in Java)
2757jpl_primitive_type_term_to_value(Type, Term, Val) :- 2758 once(jpl_primitive_type_term_to_value_1(Type, Term, Val)). % make deterministic
NB this oughta be done in foreign code.
2766jpl_primitive_type_term_to_value_1(boolean, @(false), @(false)). 2767jpl_primitive_type_term_to_value_1(boolean, @(true), @(true)). 2768jpl_primitive_type_term_to_value_1(char, I, I) :- 2769 integer(I), 2770 I >= 0, 2771 I =< 65535. % (2**16)-1. 2772jpl_primitive_type_term_to_value_1(byte, I, I) :- 2773 integer(I), 2774 I >= 128, % -(2**7) 2775 I =< 127. % (2**7)-1 2776jpl_primitive_type_term_to_value_1(short, I, I) :- 2777 integer(I), 2778 I >= -32768, % -(2**15) 2779 I =< 32767. % (2**15)-1 2780jpl_primitive_type_term_to_value_1(int, I, I) :- 2781 integer(I), 2782 I >= -2147483648, % -(2**31) 2783 I =< 2147483647. % (2**31)-1 2784jpl_primitive_type_term_to_value_1(long, I, I) :- 2785 integer(I), 2786 I >= -9223372036854775808, % -(2**63) 2787 I =< 9223372036854775807. % (2**63)-1 2788jpl_primitive_type_term_to_value_1(float, V, F) :- 2789 ( integer(V) 2790 -> F is float(V) 2791 ; float(V) 2792 -> F = V 2793 ). 2794jpl_primitive_type_term_to_value_1(double, V, F) :- 2795 ( integer(V) 2796 -> F is float(V) 2797 ; float(V) 2798 -> F = V 2799 ). 2800 2801 2802jpl_primitive_type_to_ancestor_types(T, Ts) :- 2803 ( jpl_primitive_type_super_type(T, Ta) 2804 -> Ts = [Ta|Tas], 2805 jpl_primitive_type_to_ancestor_types(Ta, Tas) 2806 ; Ts = [] 2807 ). 2808 2809 2810jpl_primitive_type_to_super_type(T, Tx) :- 2811 jpl_primitive_type_super_type(T, Tx).
Type is its type.
2820jpl_ref_to_type(Ref, T) :-
2821 ( Ref == @(null)
2822 -> T = null
2823 ; Ref == @(void)
2824 -> T = void
2825 ; jpl_object_to_type(Ref, T)
2826 ).
Type is its type (either from the cache or by reflection). OBSOLETE
2836jpl_tag_to_type(Tag, Type) :-
2837 jni_tag_to_iref(Tag, Iref),
2838 ( jpl_iref_type_cache(Iref, T)
2839 -> true % T is Tag's type
2840 ; jpl_object_to_class(@(Tag), Cobj), % else get ref to class obj
2841 jpl_class_to_type(Cobj, T), % get type of class it denotes
2842 jpl_assert(jpl_iref_type_cache(Iref,T))
2843 ),
2844 Type = T.
This succeeds iff TypeX is assignable to TypeY.
2853jpl_type_fits_type(Tx, Ty) :- 2854 once(jpl_type_fits_type_1(Tx, Ty)). % make deterministic
2861jpl_type_fits_type_1(T, T). 2862jpl_type_fits_type_1(class(Ps1,Cs1), class(Ps2,Cs2)) :- 2863 jpl_type_to_class(class(Ps1,Cs1), C1), 2864 jpl_type_to_class(class(Ps2,Cs2), C2), 2865 jIsAssignableFrom(C1, C2). 2866jpl_type_fits_type_1(array(T1), class(Ps2,Cs2)) :- 2867 jpl_type_to_class(array(T1), C1), 2868 jpl_type_to_class(class(Ps2,Cs2), C2), 2869 jIsAssignableFrom(C1, C2). 2870jpl_type_fits_type_1(array(T1), array(T2)) :- 2871 jpl_type_to_class(array(T1), C1), 2872 jpl_type_to_class(array(T2), C2), 2873 jIsAssignableFrom(C1, C2). 2874jpl_type_fits_type_1(null, class(_,_)). 2875jpl_type_fits_type_1(null, array(_)). 2876jpl_type_fits_type_1(T1, T2) :- 2877 jpl_type_fits_type_xprim(T1, T2). 2878 2879 2880jpl_type_fits_type_direct_prim(float, double). 2881jpl_type_fits_type_direct_prim(long, float). 2882jpl_type_fits_type_direct_prim(int, long). 2883jpl_type_fits_type_direct_prim(char, int). 2884jpl_type_fits_type_direct_prim(short, int). 2885jpl_type_fits_type_direct_prim(byte, short). 2886 2887 2888jpl_type_fits_type_direct_xprim(Tp, Tq) :- 2889 jpl_type_fits_type_direct_prim(Tp, Tq). 2890jpl_type_fits_type_direct_xprim(Tp, Tq) :- 2891 jpl_type_fits_type_direct_xtra(Tp, Tq).
char_int
, char_short
and char_byte
2899jpl_type_fits_type_direct_xtra(char_int, int). % char_int is a direct subtype of int 2900jpl_type_fits_type_direct_xtra(char_int, char). % etc. 2901jpl_type_fits_type_direct_xtra(char_short, short). 2902jpl_type_fits_type_direct_xtra(char_short, char). 2903jpl_type_fits_type_direct_xtra(char_byte, byte). 2904jpl_type_fits_type_direct_xtra(char_byte, char). 2905jpl_type_fits_type_direct_xtra(overlong, float). % 6/Oct/2006 experiment
2912jpl_type_fits_type_xprim(Tp, T) :-
2913 jpl_type_fits_type_direct_xprim(Tp, Tq),
2914 ( Tq = T
2915 ; jpl_type_fits_type_xprim(Tq, T)
2916 ).
2924jpl_type_to_ancestor_types(T, Tas) :-
2925 ( ( T = class(_,_)
2926 ; T = array(_)
2927 )
2928 -> jpl_type_to_class(T, C),
2929 jpl_class_to_ancestor_classes(C, Cas),
2930 jpl_classes_to_types(Cas, Tas)
2931 ; jpl_primitive_type_to_ancestor_types(T, Tas)
2932 -> true
2933 ).
CanonicalType will be equivalent and canonical.
Example
?- jpl:jpl_type_to_canonical_type(class([],[byte]), T). T = byte.
2948jpl_type_to_canonical_type(array(T), array(Tc)) :- 2949 !, 2950 jpl_type_to_canonical_type(T, Tc). 2951jpl_type_to_canonical_type(class([],[void]), void) :- 2952 !. 2953jpl_type_to_canonical_type(class([],[N]), N) :- 2954 jpl_primitive_type(N), 2955 !. 2956jpl_type_to_canonical_type(class(Ps,Cs), class(Ps,Cs)) :- 2957 !. 2958jpl_type_to_canonical_type(void, void) :- 2959 !. 2960jpl_type_to_canonical_type(P, P) :- 2961 jpl_primitive_type(P).
Incomplete types are now never cached (or otherwise passed around).
jFindClass throws an exception if FCN can't be found.
2972jpl_type_to_class(Type, Class) :-
2973 (ground(Type)
2974 -> true
2975 ; throwme(jpl_type_to_class,arg1_is_var)), % outta here if not ground
2976 (jpl_class_tag_type_cache(RefB, Type)
2977 -> true
2978 ; ( jpl_type_to_java_findclass_descriptor(Type, FCN)
2979 -> jFindClass(FCN, RefB), % which caches type of RefB
2980 jpl_cache_type_of_ref(class([java,lang],['Class']), RefB) % 9/Nov/2004 bugfix (?)
2981 ),
2982 jpl_assert(jpl_class_tag_type_cache(RefB,Type))
2983 ),
2984 Class = RefB.
TODO
: I'd cache this, but I'd prefer more efficient indexing on types (hashed?)
2994jpl_type_to_java_field_descriptor(T, FD) :-
2995 % once(phrase(jpl_field_descriptor(T,slashy), Cs)), % make deterministic
2996 phrase(jpl_field_descriptor(T,slashy), Cs), % make deterministic
2997 atom_codes(FD, Cs).
TODO
: Caching might be nice (but is it worth it?)
3006jpl_type_to_java_method_descriptor(T, MD) :-
3007 % once(phrase(jpl_method_descriptor(T), Cs)), % make deterministic (should not be needed)
3008 phrase(jpl_method_descriptor(T), Cs),
3009 atom_codes(MD, Cs).
3016jpl_type_to_java_findclass_descriptor(T, FCD) :-
3017 % once(phrase(jpl_findclass_descriptor(T), Cs)), % make deterministic (should not be needed)
3018 phrase(jpl_findclass_descriptor(T), Cs),
3019 atom_codes(FCD, Cs).
SuperType is the (at most one) type which it directly implements (if it's a class).
If Type denotes a class, this works only if that class can be found.
3029jpl_type_to_super_type(T, Tx) :-
3030 ( jpl_object_type_to_super_type(T, Tx)
3031 -> true
3032 ; jpl_primitive_type_to_super_type(T, Tx)
3033 -> true
3034 ).
char_int
or array(char_byte)
ConcreteType is the preferred concrete (Java-instantiable) type.
Example
?- jpl_type_to_preferred_concrete_type(array(char_byte), T). T = array(byte).
NB introduced 16/Apr/2005 to fix bug whereby jpl_list_to_array([1,2,3],A)
failed
because the lists's inferred type of array(char_byte)
is not Java-instantiable
3053jpl_type_to_preferred_concrete_type(T, Tc) :- 3054 ( jpl_type_to_preferred_concrete_type_1(T, TcX) 3055 -> Tc = TcX 3056 ). 3057 3058 3059jpl_type_to_preferred_concrete_type_1(char_int, int). 3060jpl_type_to_preferred_concrete_type_1(char_short, short). 3061jpl_type_to_preferred_concrete_type_1(char_byte, byte). 3062jpl_type_to_preferred_concrete_type_1(array(T), array(Tc)) :- 3063 jpl_type_to_preferred_concrete_type_1(T, Tc). 3064jpl_type_to_preferred_concrete_type_1(T, T).
Used in dynamic type check when attempting to e.g. assign list of values to array.
3073jpl_types_fit_type([], _). 3074jpl_types_fit_type([T1|T1s], T2) :- 3075 jpl_type_fits_type(T1, T2), 3076 jpl_types_fit_type(T1s, T2).
3083jpl_types_fit_types([], []). 3084jpl_types_fit_types([T1|T1s], [T2|T2s]) :- 3085 jpl_type_fits_type(T1, T2), 3086 jpl_types_fit_types(T1s, T2s).
Type is its unique most specific type,
which may be one of the pseudo types char_byte
, char_short
or char_int
.
3097jpl_value_to_type(V, T) :-
3098 ground(V), % critically assumed by jpl_value_to_type_1/2
3099 ( jpl_value_to_type_1(V, Tv) % 2nd arg must be unbound
3100 -> T = Tv
3101 ).
Called solely by jpl_value_to_type/2, which commits to first solution.
NB some integer values are of JPL-peculiar uniquely most specific subtypes, i.e. char_byte, char_short, char_int but all are understood by JPL's internal utilities which call this proc.
NB we regard float as subtype of double.
NB objects and refs always have straightforward types.
3118jpl_value_to_type_1(@(false), boolean) :- !. 3119jpl_value_to_type_1(@(true), boolean) :- !. 3120jpl_value_to_type_1(A, class([java,lang],['String'])) :- % yes it's a "value" 3121 atom(A), 3122 !. 3123jpl_value_to_type_1(I, T) :- 3124 integer(I), 3125 !, 3126 ( I >= 0 3127 -> ( I < 128 -> T = char_byte 3128 ; I < 32768 -> T = char_short 3129 ; I < 65536 -> T = char_int 3130 ; I < 2147483648 -> T = int 3131 ; I =< 9223372036854775807 -> T = long 3132 ; T = overlong 3133 ) 3134 ; I >= -128 -> T = byte 3135 ; I >= -32768 -> T = short 3136 ; I >= -2147483648 -> T = int 3137 ; I >= -9223372036854775808 -> T = long 3138 ; T = overlong 3139 ). 3140jpl_value_to_type_1(F, float) :- 3141 float(F).
java.lang.Class
.
3148jpl_is_class(X) :-
3149 jpl_is_object(X),
3150 jpl_object_to_type(X, class([java,lang],['Class'])).
@(false)
, the JPL representation of the Java boolean value 'false'.
3157jpl_is_false(X) :-
3158 X == @(false).
NB JPL internal use only.
NB applications should not be messing with these.
NB a var arg may get bound.
3171jpl_is_fieldID(jfieldID(X)) :-
3172 integer(X).
NB JPL internal use only.
NB applications should not be messing with these.
NB a var arg may get bound.
3185jpl_is_methodID(jmethodID(X)) :- % NB a var arg may get bound...
3186 integer(X).
@(null)
, the JPL representation of Java's 'null' reference.
3193jpl_is_null(X) :-
3194 X == @(null).
NB this checks only syntax, not whether the object exists.
3203jpl_is_object(X) :-
3204 blob(X, jref).
3211jpl_is_object_type(T) :-
3212 \+ var(T),
3213 jpl_non_var_is_object_type(T).
3222jpl_is_ref(Term) :-
3223 ( jpl_is_object(Term)
3224 -> true
3225 ; jpl_is_null(Term)
3226 -> true
3227 ).
@(true)
, the JPL representation of the Java
boolean value 'true'.
3235jpl_is_true(X) :-
3236 X == @(true).
3242jpl_is_type(X) :-
3243 ground(X),
3244 jpl_ground_is_type(X).
@(void)
, the JPL representation of the pseudo
Java value 'void' (which is returned by jpl_call/4 when invoked on
void methods).
NB you can try passing 'void' back to Java, but it won't ever be interested.
3255jpl_is_void(X) :-
3256 X == @(void).
@(false)
, the JPL representation of the Java boolean value
'false'.
3265jpl_false(@(false)).
@(null)
, the JPL representation of Java's 'null' reference.
3273jpl_null(@(null)).
@(true)
, the JPL representation of the Java boolean value
'true'.
3282jpl_true(@(true)).
@(void)
, the JPL representation of the pseudo Java value
'void'.
3292jpl_void(@(void)).
Length is the length of that array. This is a utility predicate, defined thus:
jpl_array_to_length(A, N) :- ( jpl_ref_to_type(A, array(_)) -> jGetArrayLength(A, N) ).
3309jpl_array_to_length(A, N) :-
3310 ( jpl_ref_to_type(A, array(_)) % can this be done cheaper e.g. in foreign code?
3311 -> jGetArrayLength(A, N) % *must* be array, else undefined (crash?)
3312 ).
Elements is a Prolog list of JPL representations of the array's elements (values or references, as appropriate). This is a utility predicate, defined thus:
jpl_array_to_list(A, Es) :- jpl_array_to_length(A, Len), ( Len > 0 -> LoBound is 0, HiBound is Len-1, jpl_get(A, LoBound-HiBound, Es) ; Es = [] ).
3334jpl_array_to_list(A, Es) :-
3335 jpl_array_to_length(A, Len),
3336 ( Len > 0
3337 -> LoBound is 0,
3338 HiBound is Len-1,
3339 jpl_get(A, LoBound-HiBound, Es)
3340 ; Es = []
3341 ).
NB this fails silently if
3356jpl_datums_to_array(Ds, A) :-
3357 ground(Ds),
3358 jpl_datums_to_most_specific_common_ancestor_type(Ds, T), % T may be pseudo e.g. char_byte
3359 jpl_type_to_preferred_concrete_type(T, Tc), % bugfix added 16/Apr/2005
3360 jpl_new(array(Tc), Ds, A).
3371jpl_enumeration_element(En, E) :-
3372 ( jpl_call(En, hasMoreElements, [], @(true))
3373 -> jpl_call(En, nextElement, [], Ex),
3374 ( E = Ex
3375 ; jpl_enumeration_element(En, E)
3376 )
3377 ).
Enumeration
interface.
Elements is a Prolog list of JPL references to the enumerated objects. This is a utility predicate, defined thus:
jpl_enumeration_to_list(Enumeration, Es) :- ( jpl_call(Enumeration, hasMoreElements, [], @(true)) -> jpl_call(Enumeration, nextElement, [], E), Es = [E|Es1], jpl_enumeration_to_list(Enumeration, Es1) ; Es = [] ).
3398jpl_enumeration_to_list(Enumeration, Es) :-
3399 ( jpl_call(Enumeration, hasMoreElements, [], @(true))
3400 -> jpl_call(Enumeration, nextElement, [], E),
3401 Es = [E|Es1],
3402 jpl_enumeration_to_list(Enumeration, Es1)
3403 ; Es = []
3404 ).
NB String is converted to atom but Integer is presumably returned as an object ref (i.e. as elsewhere, no auto unboxing);
NB this is anachronistic: the Map interface is preferred.
3416jpl_hashtable_pair(HT, K-V) :-
3417 jpl_call(HT, keys, [], Ek),
3418 jpl_enumeration_to_list(Ek, Ks),
3419 member(K, Ks),
3420 jpl_call(HT, get, [K], V).
java.util.Iterator
interface.
Element is the JPL representation of the next element in the iteration. This is a utility predicate, defined thus:
jpl_iterator_element(I, E) :- ( jpl_call(I, hasNext, [], @(true)) -> ( jpl_call(I, next, [], E) ; jpl_iterator_element(I, E) ) ).
3440jpl_iterator_element(I, E) :-
3441 ( jpl_call(I, hasNext, [], @(true))
3442 -> ( jpl_call(I, next, [], E)
3443 ; jpl_iterator_element(I, E)
3444 )
3445 ).
If Datums have a most specific common supertype, then Array is a JPL reference to a new Java array, whose base type is that common supertype, and whose respective elements are the Java values or objects represented by Datums.
3458jpl_list_to_array(Ds, A) :-
3459 jpl_datums_to_array(Ds, A).
Array is a JPL reference to a new Java array of org.jpl7.Term
,
whose elements represent the respective members of the list.
3469jpl_terms_to_array(Ts, A) :- 3470 jpl_terms_to_array_1(Ts, Ts2), 3471 jpl_new(array(class([org,jpl7],['Term'])), Ts2, A). 3472 3473 3474jpl_terms_to_array_1([], []). 3475jpl_terms_to_array_1([T|Ts], [{T}|Ts2]) :- 3476 jpl_terms_to_array_1(Ts, Ts2).
3485jpl_array_to_terms(JRef, Terms) :-
3486 jpl_call('org.jpl7.Util', termArrayToList, [JRef], {Terms}).
java.util.Map
interface
This generates each Key-Value pair from the Map, e.g.
?- jpl_call('java.lang.System', getProperties, [], Map), jpl_map_element(Map, E). Map = @<jref>(0x20b5c38), E = 'java.runtime.name'-'Java(TM) SE Runtime Environment' ; Map = @<jref>(0x20b5c38), E = 'sun.boot.library.path'-'C:\\Program Files\\Java\\jre7\\bin' etc.
This is a utility predicate, defined thus:
jpl_map_element(Map, K-V) :- jpl_call(Map, entrySet, [], ES), jpl_set_element(ES, E), jpl_call(E, getKey, [], K), jpl_call(E, getValue, [], V).
3515jpl_map_element(Map, K-V) :-
3516 jpl_call(Map, entrySet, [], ES),
3517 jpl_set_element(ES, E),
3518 jpl_call(E, getKey, [], K),
3519 jpl_call(E, getValue, [], V).
java.util.Set
interface.
On backtracking, Element is bound to a JPL representation of each element of Set. This is a utility predicate, defined thus:
jpl_set_element(S, E) :- jpl_call(S, iterator, [], I), jpl_iterator_element(I, E).
3536jpl_set_element(S, E) :-
3537 jpl_call(S, iterator, [], I),
3538 jpl_iterator_element(I, E).
3550jpl_servlet_byref(Config, Request, Response) :-
3551 jpl_call(Config, getServletContext, [], Context),
3552 jpl_call(Response, setStatus, [200], _),
3553 jpl_call(Response, setContentType, ['text/html'], _),
3554 jpl_call(Response, getWriter, [], W),
3555 jpl_call(W, println, ['<html><head></head><body><h2>jpl_servlet_byref/3 says:</h2><pre>'], _),
3556 jpl_call(W, println, ['\nservlet context stuff:'], _),
3557 jpl_call(Context, getInitParameterNames, [], ContextInitParameterNameEnum),
3558 jpl_enumeration_to_list(ContextInitParameterNameEnum, ContextInitParameterNames),
3559 length(ContextInitParameterNames, NContextInitParameterNames),
3560 atomic_list_concat(['\tContext.InitParameters = ',NContextInitParameterNames], NContextInitParameterNamesMsg),
3561 jpl_call(W, println, [NContextInitParameterNamesMsg], _),
3562 ( member(ContextInitParameterName, ContextInitParameterNames),
3563 jpl_call(Context, getInitParameter, [ContextInitParameterName], ContextInitParameter),
3564 atomic_list_concat(['\t\tContext.InitParameter[',ContextInitParameterName,'] = ',ContextInitParameter], ContextInitParameterMsg),
3565 jpl_call(W, println, [ContextInitParameterMsg], _),
3566 fail
3567 ; true
3568 ),
3569 jpl_call(Context, getMajorVersion, [], MajorVersion),
3570 atomic_list_concat(['\tContext.MajorVersion = ',MajorVersion], MajorVersionMsg),
3571 jpl_call(W, println, [MajorVersionMsg], _),
3572 jpl_call(Context, getMinorVersion, [], MinorVersion),
3573 atomic_list_concat(['\tContext.MinorVersion = ',MinorVersion], MinorVersionMsg),
3574 jpl_call(W, println, [MinorVersionMsg], _),
3575 jpl_call(Context, getServerInfo, [], ServerInfo),
3576 atomic_list_concat(['\tContext.ServerInfo = ',ServerInfo], ServerInfoMsg),
3577 jpl_call(W, println, [ServerInfoMsg], _),
3578 jpl_call(W, println, ['\nservlet config stuff:'], _),
3579 jpl_call(Config, getServletName, [], ServletName),
3580 ( ServletName == @(null)
3581 -> ServletNameAtom = null
3582 ; ServletNameAtom = ServletName
3583 ),
3584 atomic_list_concat(['\tConfig.ServletName = ',ServletNameAtom], ServletNameMsg),
3585 jpl_call(W, println, [ServletNameMsg], _),
3586 jpl_call(Config, getInitParameterNames, [], ConfigInitParameterNameEnum),
3587 jpl_enumeration_to_list(ConfigInitParameterNameEnum, ConfigInitParameterNames),
3588 length(ConfigInitParameterNames, NConfigInitParameterNames),
3589 atomic_list_concat(['\tConfig.InitParameters = ',NConfigInitParameterNames], NConfigInitParameterNamesMsg),
3590 jpl_call(W, println, [NConfigInitParameterNamesMsg], _),
3591 ( member(ConfigInitParameterName, ConfigInitParameterNames),
3592 jpl_call(Config, getInitParameter, [ConfigInitParameterName], ConfigInitParameter),
3593 atomic_list_concat(['\t\tConfig.InitParameter[',ConfigInitParameterName,'] = ',ConfigInitParameter], ConfigInitParameterMsg),
3594 jpl_call(W, println, [ConfigInitParameterMsg], _),
3595 fail
3596 ; true
3597 ),
3598 jpl_call(W, println, ['\nrequest stuff:'], _),
3599 jpl_call(Request, getAttributeNames, [], AttributeNameEnum),
3600 jpl_enumeration_to_list(AttributeNameEnum, AttributeNames),
3601 length(AttributeNames, NAttributeNames),
3602 atomic_list_concat(['\tRequest.Attributes = ',NAttributeNames], NAttributeNamesMsg),
3603 jpl_call(W, println, [NAttributeNamesMsg], _),
3604 ( member(AttributeName, AttributeNames),
3605 jpl_call(Request, getAttribute, [AttributeName], Attribute),
3606 jpl_call(Attribute, toString, [], AttributeString),
3607 atomic_list_concat(['\t\tRequest.Attribute[',AttributeName,'] = ',AttributeString], AttributeMsg),
3608 jpl_call(W, println, [AttributeMsg], _),
3609 fail
3610 ; true
3611 ),
3612 jpl_call(Request, getCharacterEncoding, [], CharacterEncoding),
3613 ( CharacterEncoding == @(null)
3614 -> CharacterEncodingAtom = ''
3615 ; CharacterEncodingAtom = CharacterEncoding
3616 ),
3617 atomic_list_concat(['\tRequest.CharacterEncoding',' = ',CharacterEncodingAtom], CharacterEncodingMsg),
3618 jpl_call(W, println, [CharacterEncodingMsg], _),
3619 jpl_call(Request, getContentLength, [], ContentLength),
3620 atomic_list_concat(['\tRequest.ContentLength',' = ',ContentLength], ContentLengthMsg),
3621 jpl_call(W, println, [ContentLengthMsg], _),
3622 jpl_call(Request, getContentType, [], ContentType),
3623 ( ContentType == @(null)
3624 -> ContentTypeAtom = ''
3625 ; ContentTypeAtom = ContentType
3626 ),
3627 atomic_list_concat(['\tRequest.ContentType',' = ',ContentTypeAtom], ContentTypeMsg),
3628 jpl_call(W, println, [ContentTypeMsg], _),
3629 jpl_call(Request, getParameterNames, [], ParameterNameEnum),
3630 jpl_enumeration_to_list(ParameterNameEnum, ParameterNames),
3631 length(ParameterNames, NParameterNames),
3632 atomic_list_concat(['\tRequest.Parameters = ',NParameterNames], NParameterNamesMsg),
3633 jpl_call(W, println, [NParameterNamesMsg], _),
3634 ( member(ParameterName, ParameterNames),
3635 jpl_call(Request, getParameter, [ParameterName], Parameter),
3636 atomic_list_concat(['\t\tRequest.Parameter[',ParameterName,'] = ',Parameter], ParameterMsg),
3637 jpl_call(W, println, [ParameterMsg], _),
3638 fail
3639 ; true
3640 ),
3641 jpl_call(Request, getProtocol, [], Protocol),
3642 atomic_list_concat(['\tRequest.Protocol',' = ',Protocol], ProtocolMsg),
3643 jpl_call(W, println, [ProtocolMsg], _),
3644 jpl_call(Request, getRemoteAddr, [], RemoteAddr),
3645 atomic_list_concat(['\tRequest.RemoteAddr',' = ',RemoteAddr], RemoteAddrMsg),
3646 jpl_call(W, println, [RemoteAddrMsg], _),
3647 jpl_call(Request, getRemoteHost, [], RemoteHost),
3648 atomic_list_concat(['\tRequest.RemoteHost',' = ',RemoteHost], RemoteHostMsg),
3649 jpl_call(W, println, [RemoteHostMsg], _),
3650 jpl_call(Request, getScheme, [], Scheme),
3651 atomic_list_concat(['\tRequest.Scheme',' = ',Scheme], SchemeMsg),
3652 jpl_call(W, println, [SchemeMsg], _),
3653 jpl_call(Request, getServerName, [], ServerName),
3654 atomic_list_concat(['\tRequest.ServerName',' = ',ServerName], ServerNameMsg),
3655 jpl_call(W, println, [ServerNameMsg], _),
3656 jpl_call(Request, getServerPort, [], ServerPort),
3657 atomic_list_concat(['\tRequest.ServerPort',' = ',ServerPort], ServerPortMsg),
3658 jpl_call(W, println, [ServerPortMsg], _),
3659 jpl_call(Request, isSecure, [], @(Secure)),
3660 atomic_list_concat(['\tRequest.Secure',' = ',Secure], SecureMsg),
3661 jpl_call(W, println, [SecureMsg], _),
3662 jpl_call(W, println, ['\nHTTP request stuff:'], _),
3663 jpl_call(Request, getAuthType, [], AuthType),
3664 ( AuthType == @(null)
3665 -> AuthTypeAtom = ''
3666 ; AuthTypeAtom = AuthType
3667 ),
3668 atomic_list_concat(['\tRequest.AuthType',' = ',AuthTypeAtom], AuthTypeMsg),
3669 jpl_call(W, println, [AuthTypeMsg], _),
3670 jpl_call(Request, getContextPath, [], ContextPath),
3671 ( ContextPath == @(null)
3672 -> ContextPathAtom = ''
3673 ; ContextPathAtom = ContextPath
3674 ),
3675 atomic_list_concat(['\tRequest.ContextPath',' = ',ContextPathAtom], ContextPathMsg),
3676 jpl_call(W, println, [ContextPathMsg], _),
3677 jpl_call(Request, getCookies, [], CookieArray),
3678 ( CookieArray == @(null)
3679 -> Cookies = []
3680 ; jpl_array_to_list(CookieArray, Cookies)
3681 ),
3682 length(Cookies, NCookies),
3683 atomic_list_concat(['\tRequest.Cookies',' = ',NCookies], NCookiesMsg),
3684 jpl_call(W, println, [NCookiesMsg], _),
3685 ( nth0(NCookie, Cookies, Cookie),
3686 atomic_list_concat(['\t\tRequest.Cookie[',NCookie,']'], CookieMsg),
3687 jpl_call(W, println, [CookieMsg], _),
3688 jpl_call(Cookie, getName, [], CookieName),
3689 atomic_list_concat(['\t\t\tRequest.Cookie.Name = ',CookieName], CookieNameMsg),
3690 jpl_call(W, println, [CookieNameMsg], _),
3691 jpl_call(Cookie, getValue, [], CookieValue),
3692 atomic_list_concat(['\t\t\tRequest.Cookie.Value = ',CookieValue], CookieValueMsg),
3693 jpl_call(W, println, [CookieValueMsg], _),
3694 jpl_call(Cookie, getPath, [], CookiePath),
3695 ( CookiePath == @(null)
3696 -> CookiePathAtom = ''
3697 ; CookiePathAtom = CookiePath
3698 ),
3699 atomic_list_concat(['\t\t\tRequest.Cookie.Path = ',CookiePathAtom], CookiePathMsg),
3700 jpl_call(W, println, [CookiePathMsg], _),
3701 jpl_call(Cookie, getComment, [], CookieComment),
3702 ( CookieComment == @(null)
3703 -> CookieCommentAtom = ''
3704 ; CookieCommentAtom = CookieComment
3705 ),
3706 atomic_list_concat(['\t\t\tRequest.Cookie.Comment = ',CookieCommentAtom], CookieCommentMsg),
3707 jpl_call(W, println, [CookieCommentMsg], _),
3708 jpl_call(Cookie, getDomain, [], CookieDomain),
3709 ( CookieDomain == @(null)
3710 -> CookieDomainAtom = ''
3711 ; CookieDomainAtom = CookieDomain
3712 ),
3713 atomic_list_concat(['\t\t\tRequest.Cookie.Domain = ',CookieDomainAtom], CookieDomainMsg),
3714 jpl_call(W, println, [CookieDomainMsg], _),
3715 jpl_call(Cookie, getMaxAge, [], CookieMaxAge),
3716 atomic_list_concat(['\t\t\tRequest.Cookie.MaxAge = ',CookieMaxAge], CookieMaxAgeMsg),
3717 jpl_call(W, println, [CookieMaxAgeMsg], _),
3718 jpl_call(Cookie, getVersion, [], CookieVersion),
3719 atomic_list_concat(['\t\t\tRequest.Cookie.Version = ',CookieVersion], CookieVersionMsg),
3720 jpl_call(W, println, [CookieVersionMsg], _),
3721 jpl_call(Cookie, getSecure, [], @(CookieSecure)),
3722 atomic_list_concat(['\t\t\tRequest.Cookie.Secure',' = ',CookieSecure], CookieSecureMsg),
3723 jpl_call(W, println, [CookieSecureMsg], _),
3724 fail
3725 ; true
3726 ),
3727 jpl_call(W, println, ['</pre></body></html>'], _),
3728 true.
3738jpl_servlet_byval(MM, CT, Ba) :-
3739 CT = 'text/html',
3740 multimap_to_atom(MM, MMa),
3741 atomic_list_concat(['<html><head></head><body>','<h2>jpl_servlet_byval/3 says:</h2><pre>', MMa,'</pre></body></html>'], Ba).
3748is_pair(Key-_Val) :- 3749 ground(Key). 3750 3751 3752is_pairs(List) :- 3753 is_list(List), 3754 maplist(is_pair, List). 3755 3756 3757multimap_to_atom(KVs, A) :- 3758 multimap_to_atom_1(KVs, '', Cz, []), 3759 flatten(Cz, Cs), 3760 atomic_list_concat(Cs, A). 3761 3762 3763multimap_to_atom_1([], _, Cs, Cs). 3764multimap_to_atom_1([K-V|KVs], T, Cs1, Cs0) :- 3765 Cs1 = [T,K,' = '|Cs2], 3766 ( is_list(V) 3767 -> ( is_pairs(V) 3768 -> V = V2 3769 ; findall(N-Ve, nth1(N, V, Ve), V2) 3770 ), 3771 T2 = [' ',T], 3772 Cs2 = ['\n'|Cs2a], 3773 multimap_to_atom_1(V2, T2, Cs2a, Cs3) 3774 ; to_atom(V, AV), 3775 Cs2 = [AV,'\n'|Cs3] 3776 ), 3777 multimap_to_atom_1(KVs, T, Cs3, Cs0).
3786to_atom(Term, Atom) :-
3787 ( atom(Term)
3788 -> Atom = Term % avoid superfluous quotes
3789 ; term_to_atom(Term, Atom)
3790 ).
3797jpl_pl_syntax(Syntax) :- 3798 ( [] == '[]' 3799 -> Syntax = traditional 3800 ; Syntax = modern 3801 ). 3802 3803 /******************************* 3804 * MESSAGES * 3805 *******************************/ 3806 3807:- multifile 3808 prolog:error_message/3. 3809 3810prologerror_message(java_exception(Ex)) --> 3811 ( { jpl_call(Ex, toString, [], Msg) 3812 } 3813 -> [ 'Java exception: ~w'-[Msg] ] 3814 ; [ 'Java exception: ~w'-[Ex] ] 3815 ). 3816 3817 3818 /******************************* 3819 * PATHS * 3820 *******************************/ 3821 3822:- multifile user:file_search_path/2. 3823:- dynamic user:file_search_path/2. 3824 3825user:file_search_path(jar, swi(lib)). 3826 3827classpath(DirOrJar) :- 3828 getenv('CLASSPATH', ClassPath), 3829 search_path_separator(Sep), 3830 atomic_list_concat(Elems, Sep, ClassPath), 3831 member(DirOrJar, Elems).
3840add_search_path(Path, Dir) :-
3841 ( getenv(Path, Old)
3842 -> search_path_separator(Sep),
3843 ( atomic_list_concat(Current, Sep, Old),
3844 memberchk(Dir, Current)
3845 -> true % already present
3846 ; atomic_list_concat([Old, Sep, Dir], New),
3847 ( debugging(jpl(path))
3848 -> env_var_separators(A,Z),
3849 debug(jpl(path), 'Set ~w~w~w to ~p', [A,Path,Z,New])
3850 ; true
3851 ),
3852 setenv(Path, New)
3853 )
3854 ; setenv(Path, Dir)
3855 ).
PATH
, LD_LIBRARY_PATH
,
CLASSPATH
, etc.3862search_path_separator((;)) :- 3863 current_prolog_flag(windows, true), 3864 !. 3865search_path_separator(:). 3866 3867env_var_separators('%','%') :- 3868 current_prolog_flag(windows, true), 3869 !. 3870env_var_separators($,''). 3871 3872 3873 /******************************* 3874 * LOAD THE JVM * 3875 *******************************/
execv()
yourself, but
this doesn't work if we want to load Java on demand or if Prolog
itself is embedded in another application.
So, after reading lots of pages on the web, I decided checking the environment and producing a sensible error message is the best we can do.
Please not that Java2 doesn't require $CLASSPATH to be set, so we do not check for that.
3893check_java_environment :- 3894 current_prolog_flag(apple, true), 3895 !, 3896 print_message(error, jpl(run(jpl_config_dylib))). 3897check_java_environment :- 3898 check_lib(jvm). 3899 3900check_lib(Name) :- 3901 check_shared_object(Name, File, EnvVar, Absolute), 3902 ( Absolute == (-) 3903 -> env_var_separators(A, Z), 3904 format(string(Msg), 'Please add directory holding ~w to ~w~w~w', 3905 [ File, A, EnvVar, Z ]), 3906 throwme(check_lib,lib_not_found(Name,Msg)) 3907 ; true 3908 ).
3917check_shared_object(Name, File, EnvVar, Absolute) :- 3918 libfile(Name, File), 3919 library_search_path(Path, EnvVar), 3920 ( member(Dir, Path), 3921 atomic_list_concat([Dir, File], /, Absolute), 3922 exists_file(Absolute) 3923 -> true 3924 ; Absolute = (-) 3925 ). 3926 3927libfile(Base, File) :- 3928 current_prolog_flag(unix, true), 3929 !, 3930 atom_concat(lib, Base, F0), 3931 current_prolog_flag(shared_object_extension, Ext), 3932 file_name_extension(F0, Ext, File). 3933libfile(Base, File) :- 3934 current_prolog_flag(windows, true), 3935 !, 3936 current_prolog_flag(shared_object_extension, Ext), 3937 file_name_extension(Base, Ext, File).
3945library_search_path(Path, EnvVar) :-
3946 current_prolog_flag(shared_object_search_path, EnvVar),
3947 search_path_separator(Sep),
3948 ( getenv(EnvVar, Env),
3949 atomic_list_concat(Path, Sep, Env)
3950 -> true
3951 ; Path = []
3952 ).
CLASSPATH
to facilitate callbacks. If jpl.jar
is
already in CLASSPATH, do nothing. Note that this may result in the
user picking up a different version of jpl.jar
. We'll assume the
user is right in this case.
3966add_jpl_to_classpath :- 3967 classpath(Jar), 3968 file_base_name(Jar, 'jpl.jar'), 3969 !. 3970add_jpl_to_classpath :- 3971 classpath(Dir), 3972 ( sub_atom(Dir, _, _, 0, /) 3973 -> atom_concat(Dir, 'jpl.jar', File) 3974 ; atom_concat(Dir, '/jpl.jar', File) 3975 ), 3976 access_file(File, read), 3977 !. 3978add_jpl_to_classpath :- 3979 absolute_file_name(jar('jpl.jar'), JplJAR, 3980 [ access(read) 3981 ]), 3982 !, 3983 ( getenv('CLASSPATH', Old) 3984 -> search_path_separator(Separator), 3985 atomic_list_concat([JplJAR, Old], Separator, New) 3986 ; New = JplJAR 3987 ), 3988 setenv('CLASSPATH', New).
loadLibrary()
call used by jpl.jar adds the lib* prefix.
In Windows we should not use foreign(jpl)
as this eventually
calls LoadLibrary() with an absolute path, disabling the Windows DLL
search process for the dependent jvm.dll
and possibly other Java
dll dependencies.
4002libjpl(File) :-
4003 ( current_prolog_flag(unix, true)
4004 -> File = foreign(libjpl)
4005 ; File = foreign(jpl) % Windows
4006 ).
4015add_jpl_to_ldpath(JPL) :- 4016 absolute_file_name(JPL, File, 4017 [ file_type(executable), 4018 access(read), 4019 file_errors(fail) 4020 ]), 4021 !, 4022 file_directory_name(File, Dir), 4023 prolog_to_os_filename(Dir, OsDir), 4024 extend_java_library_path(OsDir), 4025 current_prolog_flag(shared_object_search_path, PathVar), 4026 add_search_path(PathVar, OsDir). 4027add_jpl_to_ldpath(_).
LD_LIBRARY_PATH
(DYLD_LIBRARY_PATH
on MacOS) only
once.4036:- if(current_prolog_flag(windows,true)). 4037add_java_to_ldpath :- 4038 current_prolog_flag(windows, true), 4039 !, 4040 phrase(java_dirs, Extra), 4041 ( Extra \== [] 4042 -> print_message(informational, extend_ld_path(Extra)), 4043 maplist(extend_dll_search_path, Extra) 4044 ; true 4045 ). 4046:- endif. 4047add_java_to_ldpath.
4056:- if(current_prolog_flag(windows,true)). 4057extend_dll_search_path(Dir) :- 4058 win_add_dll_directory(Dir), 4059 ( current_prolog_flag(wine_version, _) 4060 -> prolog_to_os_filename(Dir, OSDir), 4061 ( getenv('PATH', Path0) 4062 -> atomic_list_concat([Path0, OSDir], ';', Path), 4063 setenv('PATH', Path) 4064 ; setenv('PATH', OSDir) 4065 ) 4066 ; true 4067 ). 4068:- endif.
-Djava.library.path
init
options.
4075extend_java_library_path(OsDir) :-
4076 jpl_get_default_jvm_opts(Opts0),
4077 ( select(PathOpt0, Opts0, Rest),
4078 sub_atom(PathOpt0, 0, _, _, '-Djava.library.path=')
4079 -> search_path_separator(Separator),
4080 atomic_list_concat([PathOpt0, Separator, OsDir], PathOpt),
4081 NewOpts = [PathOpt|Rest]
4082 ; atom_concat('-Djava.library.path=', OsDir, PathOpt),
4083 NewOpts = [PathOpt|Opts0]
4084 ),
4085 debug(jpl(path), 'Setting Java options to ~p', [NewOpts]),
4086 jpl_set_default_jvm_opts(NewOpts).
4093java_dirs --> 4094 % JDK directories 4095 java_dir(jvm, '/jre/bin/client'), 4096 java_dir(jvm, '/jre/bin/server'), 4097 java_dir(java, '/jre/bin'), 4098 % JRE directories 4099 java_dir(jvm, '/bin/client'), 4100 java_dir(jvm, '/bin/server'), 4101 java_dir(java, '/bin'). 4102 4103java_dir(DLL, _SubPath) --> 4104 { check_shared_object(DLL, _, _Var, Abs), 4105 Abs \== (-) 4106 }, 4107 !. 4108java_dir(_DLL, SubPath) --> 4109 { java_home(JavaHome), 4110 atom_concat(JavaHome, SubPath, SubDir), 4111 exists_directory(SubDir) 4112 }, 4113 !, 4114 [SubDir]. 4115java_dir(_, _) --> [].
4124java_home_win_key( 4125 jdk, 4126 'HKEY_LOCAL_MACHINE/Software/JavaSoft/JDK'). % new style 4127java_home_win_key( 4128 jdk, 4129 'HKEY_LOCAL_MACHINE/Software/JavaSoft/Java Development Kit'). 4130java_home_win_key( 4131 jre, 4132 'HKEY_LOCAL_MACHINE/Software/JavaSoft/JRE'). 4133java_home_win_key( 4134 jre, 4135 'HKEY_LOCAL_MACHINE/Software/JavaSoft/Java Runtime Environment'). 4136 4137java_home(Home) :- 4138 getenv('JAVA_HOME', Home), 4139 exists_directory(Home), 4140 !. 4141:- if(current_prolog_flag(windows, true)). 4142java_home(Home) :- 4143 java_home_win_key(_, Key0), % TBD: user can't choose jre or jdk 4144 catch(win_registry_get_value(Key0, 'CurrentVersion', Version), _, fail), 4145 atomic_list_concat([Key0, Version], /, Key), 4146 win_registry_get_value(Key, 'JavaHome', WinHome), 4147 prolog_to_os_filename(Home, WinHome), 4148 exists_directory(Home), 4149 !. 4150:- else. 4151java_home(Home) :- 4152 member(Home, [ '/usr/lib/java', 4153 '/usr/local/lib/java' 4154 ]), 4155 exists_directory(Home), 4156 !. 4157:- endif. 4158 4159:- dynamic 4160 jvm_ready/0. 4161:- volatile 4162 jvm_ready/0. 4163 4164setup_jvm :- 4165 jvm_ready, 4166 !. 4167setup_jvm :- 4168 add_jpl_to_classpath, 4169 add_java_to_ldpath, 4170 libjpl(JPL), 4171 catch(load_foreign_library(JPL), E, report_java_setup_problem(E)), 4172 add_jpl_to_ldpath(JPL), 4173 assert(jvm_ready). 4174 4175report_java_setup_problem(E) :- 4176 print_message(error, E), 4177 check_java_environment. 4178 4179 /******************************* 4180 * MESSAGES * 4181 *******************************/ 4182 4183:- multifile 4184 prolog:message//1. 4185 4186prologmessage(extend_ld_path(Dirs)) --> 4187 [ 'Extended DLL search path with'-[] ], 4188 dir_per_line(Dirs). 4189prologmessage(jpl(run(Command))) --> 4190 [ 'Could not find libjpl.dylib dependencies.'-[], 4191 'Please run `?- ~p.` to correct this'-[Command] 4192 ]. 4193 4194dir_per_line([]) --> []. 4195dir_per_line([H|T]) --> 4196 [ nl, ' ~q'-[H] ], 4197 dir_per_line(T). 4198 4199 /**************************************************************************** 4200 * PARSING/GENERATING ENTITY NAME / FINDCLASS DESCRIPTOR / METHOD DESCRIPTOR * 4201 ****************************************************************************/ 4202 4203% === 4204% PRINCIPLE 4205% 4206% We process list of character codes in the DCG (as opposed to lists of 4207% characters) 4208% 4209% In SWI Prolog the character codes are the Unicode code values - the DCGs 4210% looking at individual characters of a Java identifier expect this. 4211% 4212% To generate list of character codes from literals, the backquote notation 4213% can be used: 4214% 4215% ?- X=`alpha`. 4216% X = [97, 108, 112, 104, 97]. 4217% 4218% However, Jab Wielmaker says: 4219% 4220% "Please use "string" for terminals in DCGs. The SWI-Prolog DCG compiler 4221% handles these correctly and this retains compatibility." 4222% 4223% So we do that. 4224% === 4225 4226% jpl_entityname//1 4227% 4228% Relate a Java-side "entity name" (a String as returned by Class.getName()) 4229% (in the DCG accumulator as a list of Unicode code values) to JPL's 4230% Prolog-side "type term". 4231% 4232% For example: 4233% 4234% ~~~ 4235% Java-side "entity name" <-----> JPL Prolog-side "type term" 4236% "java.util.Date" class([java,util],['Date']) 4237% ~~~ 4238% 4239% @see https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Class.html#getName() 4240% 4241% Example for getName() calls generating entity names 4242% 4243% ~~~ 4244% 4245% class TJ { 4246% public static final void main(String[] argv) { 4247% 4248% System.out.println(void.class.getName()); // void 4249% System.out.println(Void.TYPE.getName()); // void 4250% System.out.println(Void.class.getName()); // java.lang.Void 4251% 4252% System.out.println(char.class.getName()); // char 4253% System.out.println(Character.TYPE.getName()); // char 4254% System.out.println(Character.class.getName()); // java.lang.Character 4255% System.out.println(Character.valueOf('x').getClass().getName()); // java.lang.Character 4256% 4257% System.out.println(int[].class.getName()); // [I 4258% System.out.println((new int[4]).getClass().getName()); // [I 4259% int[] a = {1,2,3}; System.out.println(a.getClass().getName()); // [I 4260% 4261% System.out.println(int[][].class.getName()); // [[I 4262% System.out.println((new int[4][4]).getClass().getName()); // [[I 4263% int[][] aa = {{1},{2},{3}}; System.out.println(aa.getClass().getName()); // [[I 4264% 4265% System.out.println(Integer[][].class.getName()); // [[Ljava.lang.Integer; 4266% System.out.println((new Integer[4][4]).getClass().getName()); // [[Ljava.lang.Integer; 4267% Integer[][] bb = {{1},{2},{3}}; System.out.println(bb.getClass().getName()); // [[Ljava.lang.Integer; 4268% 4269% } 4270% } 4271% ~~~ 4272% 4273% Note that We can list the possible "jpl type terms" directly in the head of 4274% jpl_entityname//1 (except for the primitives). This helps in clause selection 4275% and documentation. Note that the fact that the last two clauses T are not tagged as 4276% "primitive()" makes this representation nonuniform; should be fixed at some time. 4277% --- 4278 4279jpl_entityname(class(Ps,Cs)) --> jpl_classname(class(Ps,Cs),dotty),!. 4280jpl_entityname(array(T)) --> jpl_array_type_descriptor(array(T),dotty),!. 4281jpl_entityname(void) --> "void",!. 4282jpl_entityname(P) --> jpl_primitive_entityname(P). 4283 4284% --- 4285% The "findclass descriptor" is used for the JNI function FindClass and is 4286% either an array type descriptor with a "slashy" package name or directly 4287% a classname, also with a "slasgy" package name 4288% --- 4289 4290jpl_findclass_descriptor(array(T)) --> jpl_array_type_descriptor(array(T),slashy),!. 4291jpl_findclass_descriptor(class(Ps,Cs)) --> jpl_classname(class(Ps,Cs),slashy). 4292 4293% --- 4294% The "method descriptor" is used to find a method ID based on the method 4295% signature. It contains method arguments and type of method return value 4296% --- 4297 4298jpl_method_descriptor(method(Ts,T)) --> "(", jpl_method_descriptor_args(Ts), ")", jpl_method_descriptor_retval(T). 4299 4300jpl_method_descriptor_args([T|Ts]) --> jpl_field_descriptor(T,slashy), !, jpl_method_descriptor_args(Ts). 4301jpl_method_descriptor_args([]) --> []. 4302 4303jpl_method_descriptor_retval(void) --> "V". 4304jpl_method_descriptor_retval(T) --> jpl_field_descriptor(T,slashy). 4305 4306% --- 4307% The "binary classname" (i.e. the classname as it appears in binaries) as 4308% specified in The "Java Language Specification". 4309% See "Binary Compatibility" - "The Form of a Binary" 4310% https://docs.oracle.com/javase/specs/jls/se14/html/jls-13.html#jls-13.1 4311% which points to the "fully qualified name" and "canonical name" 4312% https://docs.oracle.com/javase/specs/jls/se14/html/jls-6.html#jls-6.7 4313% 4314% For JNI, we can switch to "slashy" mode instead of the "dotty" mode, which 4315% technically makes this NOT the "binary classname", but we keep the predicate name. 4316% --- 4317 4318jpl_classname(class(Ps,Cs),Mode) --> jpl_package_parts(Ps,Mode), jpl_class_parts(Cs). 4319 4320% --- 4321% The qualified name of the package (which may be empty if it is the 4322% unnamed package). This is a series of Java identifiers separated by dots, but 4323% in order to reduce codesize, we switch to the "slash" separator depending 4324% on a second argument, the mode, which is either "dotty" or "slashy". 4325% "The fully qualified name of a named package that is not a subpackage of a 4326% named package is its simple name." ... "A simple name is a single identifier." 4327% https://docs.oracle.com/javase/specs/jls/se14/html/jls-6.html#jls-6.7 4328% Note that the last '.' is not considered a separator towards the subsequent 4329% class parts but as a terminator of the package parts sequence (it's a view 4330% less demanding of backtracking) 4331% --- 4332 4333jpl_package_parts([A|As],dotty) --> jpl_java_id(A), ".", !, jpl_package_parts(As,dotty). 4334jpl_package_parts([A|As],slashy) --> jpl_java_id(A), "/", !, jpl_package_parts(As,slashy). 4335jpl_package_parts([],_) --> []. 4336 4337% --- 4338% The class parts of a class name (everything beyond the last dot 4339% of the package prefix, if it exists). This comes from "13.1 - The form of 4340% a binary", where it is laid out a bit confusingly. 4341% https://docs.oracle.com/javase/specs/jls/se14/html/jls-13.html#jls-13.1 4342% 4343% PROBLEM 2020-08: 4344% 4345% Here is an ambiguity that I haven't been able to resolve: '$' is a perfectly 4346% legitimate character both at the start and in the middle of a classname, 4347% in fact you can create classes with '$' inside the classname and they compile 4348% marvelously (try it!). However it is also used as separator for inner class 4349% names ... but not really! In fact, it is just a concatentation character for 4350% a _generated class name_ (that makes sense - an inner class is a syntactic 4351% construct of Java the Language, but of no concern to the JVM, not even for 4352% access checking because the compiler is supposed to have bleached out any 4353% problemtic code). 4354% Parsing such a generated class name can go south in several different ways: 4355% '$' at the begging, '$' at the end, multiple runs of '$$$' .. one should not 4356% attempt to do it! 4357% But the original JPL code does, so we keep this practice for now. 4358% --- 4359 4360jpl_class_parts(Cs) --> { nonvar(Cs), ! }, % guard 4361 { atomic_list_concat(Cs,'$',A) }, % fuse known Cs with '$' 4362 jpl_java_type_id(A). % verify it & insert it into list 4363 4364jpl_class_parts(Cs) --> { var(Cs), ! }, % guard 4365 jpl_java_type_id(A), % grab an id including its '$' 4366 { messy_dollar_split(A,Cs) }. % split it along '$' 4367 4368 4369% --- 4370% "field descriptors" appear in method signatures or inside array type 4371% descriptors (which are itself field descriptors) 4372% --- 4373 4374jpl_field_descriptor(class(Ps,Cs),Mode) --> jpl_reference_type_descriptor(class(Ps,Cs),Mode),!. 4375jpl_field_descriptor(array(T),Mode) --> jpl_array_type_descriptor(array(T),Mode),!. 4376jpl_field_descriptor(T,_) --> jpl_primitive_type_descriptor(T). % sadly untagged with primitive(_) in the head 4377 4378jpl_reference_type_descriptor(class(Ps,Cs),Mode) --> "L", jpl_classname(class(Ps,Cs),Mode), ";". 4379 4380jpl_array_type_descriptor(array(T),Mode) --> "[", jpl_field_descriptor(T,Mode). 4381 4382% --- 4383% Breaking a bare classname at the '$' 4384% --- 4385% Heuristic: Only a '$' flanked to the left by a valid character 4386% that is a non-dollar and to the right by a valid character that 4387% may or may not be a dollar gives rise to split. 4388% 4389% The INVERSE of messy_dollar_split/2 is atomic_list_concat/3 4390 4391messy_dollar_split(A,Out) :- 4392 assertion(A \== ''), 4393 atom_chars(A,Chars), 4394 append([''|Chars],[''],GAChars), % GA is a "guarded A char list" flanked by empties and contains at least 3 chars 4395 triple_process(GAChars,[],[],RunsOut), 4396 postprocess_messy_dollar_split_runs(RunsOut,Out). 4397 4398postprocess_messy_dollar_split_runs(Runs,Out) :- 4399 reverse(Runs,R1), 4400 maplist([Rin,Rout]>>reverse(Rin,Rout),R1,O1), 4401 maplist([Chars,Atom]>>atom_chars(Atom,Chars),O1,Out). 4402 4403% Split only between P and N, dropping C, when: 4404% 1) C is a $ and P is not a dollar and not a start of line 4405% 2) N is not the end of line 4406 4407triple_process([P,'$',N|Rest],Run,Runs,Out) :- 4408 N \== '', P \== '$' , P \== '',!, 4409 triple_process(['',N|Rest],[],[Run|Runs],Out). 4410 4411triple_process(['','$',N|Rest],Run,Runs,Out) :- 4412 !, 4413 triple_process(['',N|Rest],['$'|Run],Runs,Out). 4414 4415triple_process([_,C,N|Rest],Run,Runs,Out) :- 4416 C \== '$',!, 4417 triple_process([C,N|Rest],[C|Run],Runs,Out). 4418 4419triple_process([_,C,''],Run,Runs,[[C|Run]|Runs]) :- !. 4420 4421triple_process([_,''],Run,Runs,[Run|Runs]). 4422 4423% === 4424% Low-level DCG rules 4425% === 4426 4427% --- 4428% A Java type identifier is a Java identifier different from "var" and "yield" 4429% --- 4430 4431jpl_java_type_id(I) --> jpl_java_id(I), { \+memberchk(I,[var,yield]) }. 4432 4433% --- 4434% The Java identifier is described at 4435% https://docs.oracle.com/javase/specs/jls/se14/html/jls-3.html#jls-Identifier 4436% --- 4437 4438jpl_java_id(I) --> jpl_java_id_raw(I), 4439 { \+jpl_java_keyword(I), 4440 \+jpl_java_boolean_literal(I), 4441 \+jpl_java_null_literal(I) }. 4442 4443% --- 4444% For direct handling of an identifier, we suffer symmetry breakdown. 4445% --- 4446 4447jpl_java_id_raw(A) --> { atom(A),! }, % guard 4448 { atom_codes(A,[C|Cs]) }, % explode A 4449 { jpl_java_id_start_char(C) }, 4450 [C], 4451 jpl_java_id_part_chars(Cs). 4452 4453% building X from the character code list 4454 4455jpl_java_id_raw(A) --> { var(A),! }, % guard 4456 [C], 4457 { jpl_java_id_start_char(C) }, 4458 jpl_java_id_part_chars(Cs), 4459 { atom_codes(A,[C|Cs]) }. % fuse A 4460 4461jpl_java_id_part_chars([C|Cs]) --> [C], { jpl_java_id_part_char(C) } ,!, jpl_java_id_part_chars(Cs). 4462jpl_java_id_part_chars([]) --> []. 4463 4464% --- 4465% jpl_primitive_in_array//1 4466% Described informally in Javadoc for Class.getName() 4467% https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Class.html#getName() 4468% The left-hand side should (the JPL type) really be tagged with primitive(boolean) etc. 4469% --- 4470 4471jpl_primitive_type_descriptor(boolean) --> "Z",!. 4472jpl_primitive_type_descriptor(byte) --> "B",!. 4473jpl_primitive_type_descriptor(char) --> "C",!. 4474jpl_primitive_type_descriptor(double) --> "D",!. 4475jpl_primitive_type_descriptor(float) --> "F",!. 4476jpl_primitive_type_descriptor(int) --> "I",!. 4477jpl_primitive_type_descriptor(long) --> "J",!. 4478jpl_primitive_type_descriptor(short) --> "S". 4479 4480% --- 4481% jpl_primitive_entityname//1 4482% These are just the primitive names. 4483% The left-hand side should (the JPL type) really be tagged with primitive(boolean) etc. 4484% --- 4485 4486jpl_primitive_entityname(boolean) --> "boolean" ,!. 4487jpl_primitive_entityname(byte) --> "byte" ,!. 4488jpl_primitive_entityname(char) --> "char" ,!. 4489jpl_primitive_entityname(double) --> "double" ,!. 4490jpl_primitive_entityname(float) --> "float" ,!. 4491jpl_primitive_entityname(int) --> "int" ,!. 4492jpl_primitive_entityname(long) --> "long" ,!. 4493jpl_primitive_entityname(short) --> "short". 4494 4495% --- 4496% Certain java keywords that may not occur as java identifier 4497% --- 4498 4499jpl_java_boolean_literal(true). 4500jpl_java_boolean_literal(false). 4501 4502jpl_java_null_literal(null). 4503 4504jpl_java_keyword('_'). 4505jpl_java_keyword(abstract). 4506jpl_java_keyword(assert). 4507jpl_java_keyword(boolean). 4508jpl_java_keyword(break). 4509jpl_java_keyword(byte). 4510jpl_java_keyword(case). 4511jpl_java_keyword(catch). 4512jpl_java_keyword(char). 4513jpl_java_keyword(class). 4514jpl_java_keyword(const). 4515jpl_java_keyword(continue). 4516jpl_java_keyword(default). 4517jpl_java_keyword(do). 4518jpl_java_keyword(double). 4519jpl_java_keyword(else). 4520jpl_java_keyword(enum). 4521jpl_java_keyword(extends). 4522jpl_java_keyword(final). 4523jpl_java_keyword(finally). 4524jpl_java_keyword(float). 4525jpl_java_keyword(for). 4526jpl_java_keyword(goto). 4527jpl_java_keyword(if). 4528jpl_java_keyword(implements). 4529jpl_java_keyword(import). 4530jpl_java_keyword(instanceof). 4531jpl_java_keyword(int). 4532jpl_java_keyword(interface). 4533jpl_java_keyword(long). 4534jpl_java_keyword(native). 4535jpl_java_keyword(new). 4536jpl_java_keyword(package). 4537jpl_java_keyword(private). 4538jpl_java_keyword(protected). 4539jpl_java_keyword(public). 4540jpl_java_keyword(return). 4541jpl_java_keyword(short). 4542jpl_java_keyword(static). 4543jpl_java_keyword(strictfp). 4544jpl_java_keyword(super). 4545jpl_java_keyword(switch). 4546jpl_java_keyword(synchronized). 4547jpl_java_keyword(this). 4548jpl_java_keyword(throw). 4549jpl_java_keyword(throws). 4550jpl_java_keyword(transient). 4551jpl_java_keyword(try). 4552jpl_java_keyword(void). 4553jpl_java_keyword(volatile). 4554jpl_java_keyword(while). 4555 4556% === 4557% Classify codepoints (i.e. integers) as "Java identifier start/part characters" 4558% 4559% A "Java identifier" starts with a "Java identifier start character" and 4560% continues with a "Java identifier part character". 4561% 4562% A "Java identifier start character" is a character for which 4563% Character.isJavaIdentifierStart(c) returns true, where "c" can be a 4564% Java char or an integer Unicode code value (basically, that's the definition). 4565% 4566% Similarly, a "Java identifier part character" is a character for which 4567% point Character.isJavaIdentifierPart(c) returns true 4568% 4569% See: 4570% 4571% https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Character.html#isJavaIdentifierStart(int) 4572% https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Character.html#isJavaIdentifierPart(int) 4573% 4574% A simple Java program was used to generate the runs of unicode character 4575% points listed below. They are searched lineraly. Generally, a 4576% code point/value encountered by jpl would be below even 255 and so be 4577% found quickly 4578% 4579% PROBLEM: 4580% 4581% 1) If the Prolog implementation does not represent characters internally 4582% with Unicode code values, i.e. if atom_codes/2 takes/returns other values 4583% than Unicode code values (may be the case for Prologs other than SWI Prolog) 4584% an implementation-dependent mapping from/to Unicode will have to be performed 4585% first! 4586% 4587% 2) Is this slow or not? It depends on what the compiler does. 4588% === 4589 4590jpl_java_id_start_char(C) :- 4591 assertion(integer(C)), 4592 java_id_start_char_ranges(Ranges), % retrieve ranges 4593 char_inside_range(C,Ranges). % check 4594 4595jpl_java_id_part_char(C) :- 4596 assertion(integer(C)), 4597 java_id_part_char_ranges(Ranges), % retrieve ranges 4598 char_inside_range(C,Ranges). % check 4599 4600char_inside_range(C,[[_Low,High]|Ranges]) :- 4601 High < C,!,char_inside_range(C,Ranges). 4602 4603char_inside_range(C,[[Low,High]|_]) :- 4604 Low =< C, C =< High. 4605 4606% --- 4607% The ranges below are generated with a Java program, then printed 4608% See "CharRangePrinter.java" 4609% Note that 36 is "$" which IS allowed as start and part character! 4610% In fact, there are class names that start with '$' (which is why the 4611% current version of JPL cannot connect to LibreOffice) 4612% --- 4613 4614java_id_start_char_ranges( 4615 [[36,36],[65,90],[95,95],[97,122],[162,165],[170,170],[181,181],[186,186], 4616 [192,214],[216,246],[248,705],[710,721],[736,740],[748,748],[750,750], 4617 [880,884],[886,887],[890,893],[895,895],[902,902],[904,906],[908,908], 4618 [910,929],[931,1013],[1015,1153],[1162,1327],[1329,1366],[1369,1369], 4619 [1376,1416],[1423,1423],[1488,1514],[1519,1522],[1547,1547],[1568,1610], 4620 [1646,1647],[1649,1747],[1749,1749],[1765,1766],[1774,1775],[1786,1788], 4621 [1791,1791],[1808,1808],[1810,1839],[1869,1957],[1969,1969],[1994,2026], 4622 [2036,2037],[2042,2042],[2046,2069],[2074,2074],[2084,2084],[2088,2088], 4623 [2112,2136],[2144,2154],[2208,2228],[2230,2237],[2308,2361],[2365,2365], 4624 [2384,2384],[2392,2401],[2417,2432],[2437,2444],[2447,2448],[2451,2472], 4625 [2474,2480],[2482,2482],[2486,2489],[2493,2493],[2510,2510],[2524,2525], 4626 [2527,2529],[2544,2547],[2555,2556],[2565,2570],[2575,2576],[2579,2600], 4627 [2602,2608],[2610,2611],[2613,2614],[2616,2617],[2649,2652],[2654,2654], 4628 [2674,2676],[2693,2701],[2703,2705],[2707,2728],[2730,2736],[2738,2739], 4629 [2741,2745],[2749,2749],[2768,2768],[2784,2785],[2801,2801],[2809,2809], 4630 [2821,2828],[2831,2832],[2835,2856],[2858,2864],[2866,2867],[2869,2873], 4631 [2877,2877],[2908,2909],[2911,2913],[2929,2929],[2947,2947],[2949,2954], 4632 [2958,2960],[2962,2965],[2969,2970],[2972,2972],[2974,2975],[2979,2980], 4633 [2984,2986],[2990,3001],[3024,3024],[3065,3065],[3077,3084],[3086,3088], 4634 [3090,3112],[3114,3129],[3133,3133],[3160,3162],[3168,3169],[3200,3200], 4635 [3205,3212],[3214,3216],[3218,3240],[3242,3251],[3253,3257],[3261,3261], 4636 [3294,3294],[3296,3297],[3313,3314],[3333,3340],[3342,3344],[3346,3386], 4637 [3389,3389],[3406,3406],[3412,3414],[3423,3425],[3450,3455],[3461,3478], 4638 [3482,3505],[3507,3515],[3517,3517],[3520,3526],[3585,3632],[3634,3635], 4639 [3647,3654],[3713,3714],[3716,3716],[3718,3722],[3724,3747],[3749,3749], 4640 [3751,3760],[3762,3763],[3773,3773],[3776,3780],[3782,3782],[3804,3807], 4641 [3840,3840],[3904,3911],[3913,3948],[3976,3980],[4096,4138],[4159,4159], 4642 [4176,4181],[4186,4189],[4193,4193],[4197,4198],[4206,4208],[4213,4225], 4643 [4238,4238],[4256,4293],[4295,4295],[4301,4301],[4304,4346],[4348,4680], 4644 [4682,4685],[4688,4694],[4696,4696],[4698,4701],[4704,4744],[4746,4749], 4645 [4752,4784],[4786,4789],[4792,4798],[4800,4800],[4802,4805],[4808,4822], 4646 [4824,4880],[4882,4885],[4888,4954],[4992,5007],[5024,5109],[5112,5117], 4647 [5121,5740],[5743,5759],[5761,5786],[5792,5866],[5870,5880],[5888,5900], 4648 [5902,5905],[5920,5937],[5952,5969],[5984,5996],[5998,6000],[6016,6067], 4649 [6103,6103],[6107,6108],[6176,6264],[6272,6276],[6279,6312],[6314,6314], 4650 [6320,6389],[6400,6430],[6480,6509],[6512,6516],[6528,6571],[6576,6601], 4651 [6656,6678],[6688,6740],[6823,6823],[6917,6963],[6981,6987],[7043,7072], 4652 [7086,7087],[7098,7141],[7168,7203],[7245,7247],[7258,7293],[7296,7304], 4653 [7312,7354],[7357,7359],[7401,7404],[7406,7411],[7413,7414],[7418,7418], 4654 [7424,7615],[7680,7957],[7960,7965],[7968,8005],[8008,8013],[8016,8023], 4655 [8025,8025],[8027,8027],[8029,8029],[8031,8061],[8064,8116],[8118,8124], 4656 [8126,8126],[8130,8132],[8134,8140],[8144,8147],[8150,8155],[8160,8172], 4657 [8178,8180],[8182,8188],[8255,8256],[8276,8276],[8305,8305],[8319,8319], 4658 [8336,8348],[8352,8383],[8450,8450],[8455,8455],[8458,8467],[8469,8469], 4659 [8473,8477],[8484,8484],[8486,8486],[8488,8488],[8490,8493],[8495,8505], 4660 [8508,8511],[8517,8521],[8526,8526],[8544,8584],[11264,11310],[11312,11358], 4661 [11360,11492],[11499,11502],[11506,11507],[11520,11557],[11559,11559], 4662 [11565,11565],[11568,11623],[11631,11631],[11648,11670],[11680,11686], 4663 [11688,11694],[11696,11702],[11704,11710],[11712,11718],[11720,11726], 4664 [11728,11734],[11736,11742],[11823,11823],[12293,12295],[12321,12329], 4665 [12337,12341],[12344,12348],[12353,12438],[12445,12447],[12449,12538], 4666 [12540,12543],[12549,12591],[12593,12686],[12704,12730],[12784,12799], 4667 [13312,19893],[19968,40943],[40960,42124],[42192,42237],[42240,42508], 4668 [42512,42527],[42538,42539],[42560,42606],[42623,42653],[42656,42735], 4669 [42775,42783],[42786,42888],[42891,42943],[42946,42950],[42999,43009], 4670 [43011,43013],[43015,43018],[43020,43042],[43064,43064],[43072,43123], 4671 [43138,43187],[43250,43255],[43259,43259],[43261,43262],[43274,43301], 4672 [43312,43334],[43360,43388],[43396,43442],[43471,43471],[43488,43492], 4673 [43494,43503],[43514,43518],[43520,43560],[43584,43586],[43588,43595], 4674 [43616,43638],[43642,43642],[43646,43695],[43697,43697],[43701,43702], 4675 [43705,43709],[43712,43712],[43714,43714],[43739,43741],[43744,43754], 4676 [43762,43764],[43777,43782],[43785,43790],[43793,43798],[43808,43814], 4677 [43816,43822],[43824,43866],[43868,43879],[43888,44002],[44032,55203], 4678 [55216,55238],[55243,55291],[63744,64109],[64112,64217],[64256,64262], 4679 [64275,64279],[64285,64285],[64287,64296],[64298,64310],[64312,64316], 4680 [64318,64318],[64320,64321],[64323,64324],[64326,64433],[64467,64829], 4681 [64848,64911],[64914,64967],[65008,65020],[65075,65076],[65101,65103], 4682 [65129,65129],[65136,65140],[65142,65276],[65284,65284],[65313,65338], 4683 [65343,65343],[65345,65370],[65382,65470],[65474,65479],[65482,65487], 4684 [65490,65495],[65498,65500],[65504,65505],[65509,65510]]). 4685 4686java_id_part_char_ranges( 4687 [[0,8],[14,27],[36,36],[48,57],[65,90],[95,95],[97,122],[127,159],[162,165], 4688 [170,170],[173,173],[181,181],[186,186],[192,214],[216,246],[248,705], 4689 [710,721],[736,740],[748,748],[750,750],[768,884],[886,887],[890,893], 4690 [895,895],[902,902],[904,906],[908,908],[910,929],[931,1013],[1015,1153], 4691 [1155,1159],[1162,1327],[1329,1366],[1369,1369],[1376,1416],[1423,1423], 4692 [1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1488,1514], 4693 [1519,1522],[1536,1541],[1547,1547],[1552,1562],[1564,1564],[1568,1641], 4694 [1646,1747],[1749,1757],[1759,1768],[1770,1788],[1791,1791],[1807,1866], 4695 [1869,1969],[1984,2037],[2042,2042],[2045,2093],[2112,2139],[2144,2154], 4696 [2208,2228],[2230,2237],[2259,2403],[2406,2415],[2417,2435],[2437,2444], 4697 [2447,2448],[2451,2472],[2474,2480],[2482,2482],[2486,2489],[2492,2500], 4698 [2503,2504],[2507,2510],[2519,2519],[2524,2525],[2527,2531],[2534,2547], 4699 [2555,2556],[2558,2558],[2561,2563],[2565,2570],[2575,2576],[2579,2600], 4700 [2602,2608],[2610,2611],[2613,2614],[2616,2617],[2620,2620],[2622,2626], 4701 [2631,2632],[2635,2637],[2641,2641],[2649,2652],[2654,2654],[2662,2677], 4702 [2689,2691],[2693,2701],[2703,2705],[2707,2728],[2730,2736],[2738,2739], 4703 [2741,2745],[2748,2757],[2759,2761],[2763,2765],[2768,2768],[2784,2787], 4704 [2790,2799],[2801,2801],[2809,2815],[2817,2819],[2821,2828],[2831,2832], 4705 [2835,2856],[2858,2864],[2866,2867],[2869,2873],[2876,2884],[2887,2888], 4706 [2891,2893],[2902,2903],[2908,2909],[2911,2915],[2918,2927],[2929,2929], 4707 [2946,2947],[2949,2954],[2958,2960],[2962,2965],[2969,2970],[2972,2972], 4708 [2974,2975],[2979,2980],[2984,2986],[2990,3001],[3006,3010],[3014,3016], 4709 [3018,3021],[3024,3024],[3031,3031],[3046,3055],[3065,3065],[3072,3084], 4710 [3086,3088],[3090,3112],[3114,3129],[3133,3140],[3142,3144],[3146,3149], 4711 [3157,3158],[3160,3162],[3168,3171],[3174,3183],[3200,3203],[3205,3212], 4712 [3214,3216],[3218,3240],[3242,3251],[3253,3257],[3260,3268],[3270,3272], 4713 [3274,3277],[3285,3286],[3294,3294],[3296,3299],[3302,3311],[3313,3314], 4714 [3328,3331],[3333,3340],[3342,3344],[3346,3396],[3398,3400],[3402,3406], 4715 [3412,3415],[3423,3427],[3430,3439],[3450,3455],[3458,3459],[3461,3478], 4716 [3482,3505],[3507,3515],[3517,3517],[3520,3526],[3530,3530],[3535,3540], 4717 [3542,3542],[3544,3551],[3558,3567],[3570,3571],[3585,3642],[3647,3662], 4718 [3664,3673],[3713,3714],[3716,3716],[3718,3722],[3724,3747],[3749,3749], 4719 [3751,3773],[3776,3780],[3782,3782],[3784,3789],[3792,3801],[3804,3807], 4720 [3840,3840],[3864,3865],[3872,3881],[3893,3893],[3895,3895],[3897,3897], 4721 [3902,3911],[3913,3948],[3953,3972],[3974,3991],[3993,4028],[4038,4038], 4722 [4096,4169],[4176,4253],[4256,4293],[4295,4295],[4301,4301],[4304,4346], 4723 [4348,4680],[4682,4685],[4688,4694],[4696,4696],[4698,4701],[4704,4744], 4724 [4746,4749],[4752,4784],[4786,4789],[4792,4798],[4800,4800],[4802,4805], 4725 [4808,4822],[4824,4880],[4882,4885],[4888,4954],[4957,4959],[4992,5007], 4726 [5024,5109],[5112,5117],[5121,5740],[5743,5759],[5761,5786],[5792,5866], 4727 [5870,5880],[5888,5900],[5902,5908],[5920,5940],[5952,5971],[5984,5996], 4728 [5998,6000],[6002,6003],[6016,6099],[6103,6103],[6107,6109],[6112,6121], 4729 [6155,6158],[6160,6169],[6176,6264],[6272,6314],[6320,6389],[6400,6430], 4730 [6432,6443],[6448,6459],[6470,6509],[6512,6516],[6528,6571],[6576,6601], 4731 [6608,6617],[6656,6683],[6688,6750],[6752,6780],[6783,6793],[6800,6809], 4732 [6823,6823],[6832,6845],[6912,6987],[6992,7001],[7019,7027],[7040,7155], 4733 [7168,7223],[7232,7241],[7245,7293],[7296,7304],[7312,7354],[7357,7359], 4734 [7376,7378],[7380,7418],[7424,7673],[7675,7957],[7960,7965],[7968,8005], 4735 [8008,8013],[8016,8023],[8025,8025],[8027,8027],[8029,8029],[8031,8061], 4736 [8064,8116],[8118,8124],[8126,8126],[8130,8132],[8134,8140],[8144,8147], 4737 [8150,8155],[8160,8172],[8178,8180],[8182,8188],[8203,8207],[8234,8238], 4738 [8255,8256],[8276,8276],[8288,8292],[8294,8303],[8305,8305],[8319,8319], 4739 [8336,8348],[8352,8383],[8400,8412],[8417,8417],[8421,8432],[8450,8450], 4740 [8455,8455],[8458,8467],[8469,8469],[8473,8477],[8484,8484],[8486,8486], 4741 [8488,8488],[8490,8493],[8495,8505],[8508,8511],[8517,8521],[8526,8526], 4742 [8544,8584],[11264,11310],[11312,11358],[11360,11492],[11499,11507], 4743 [11520,11557],[11559,11559],[11565,11565],[11568,11623],[11631,11631], 4744 [11647,11670],[11680,11686],[11688,11694],[11696,11702],[11704,11710], 4745 [11712,11718],[11720,11726],[11728,11734],[11736,11742],[11744,11775], 4746 [11823,11823],[12293,12295],[12321,12335],[12337,12341],[12344,12348], 4747 [12353,12438],[12441,12442],[12445,12447],[12449,12538],[12540,12543], 4748 [12549,12591],[12593,12686],[12704,12730],[12784,12799],[13312,19893], 4749 [19968,40943],[40960,42124],[42192,42237],[42240,42508],[42512,42539], 4750 [42560,42607],[42612,42621],[42623,42737],[42775,42783],[42786,42888], 4751 [42891,42943],[42946,42950],[42999,43047],[43064,43064],[43072,43123], 4752 [43136,43205],[43216,43225],[43232,43255],[43259,43259],[43261,43309], 4753 [43312,43347],[43360,43388],[43392,43456],[43471,43481],[43488,43518], 4754 [43520,43574],[43584,43597],[43600,43609],[43616,43638],[43642,43714], 4755 [43739,43741],[43744,43759],[43762,43766],[43777,43782],[43785,43790], 4756 [43793,43798],[43808,43814],[43816,43822],[43824,43866],[43868,43879], 4757 [43888,44010],[44012,44013],[44016,44025],[44032,55203],[55216,55238], 4758 [55243,55291],[63744,64109],[64112,64217],[64256,64262],[64275,64279], 4759 [64285,64296],[64298,64310],[64312,64316],[64318,64318],[64320,64321], 4760 [64323,64324],[64326,64433],[64467,64829],[64848,64911],[64914,64967], 4761 [65008,65020],[65024,65039],[65056,65071],[65075,65076],[65101,65103], 4762 [65129,65129],[65136,65140],[65142,65276],[65279,65279],[65284,65284], 4763 [65296,65305],[65313,65338],[65343,65343],[65345,65370],[65382,65470], 4764 [65474,65479],[65482,65487],[65490,65495],[65498,65500],[65504,65505], 4765 [65509,65510],[65529,65531]]). 4766 4767 4768 /******************************* 4769 * EXCEPTION HANDLING * 4770 *******************************/ 4771 4772% === 4773% throwme(+LookupPred,+LookupTerm) 4774% 4775% Predicate called to construct an exception term and throw it. Information 4776% about how to construct the actual exception is found by performing a lookup 4777% based on the key formed by the pair (LookupPred,LookupTerm). 4778% 4779% LookupPred : 4780% What predicate is throwing; this is an atom (a keyword) generally shaped 4781% after the actual predicate name of the throwing predicate. It is not a 4782% predicate indicator. 4783% 4784% LookupTerm : 4785% A term, possibly compound, that describes the problem somehow. It is both 4786% programmer-interpretable (but still abstract) as well as a way of passing 4787% values that can be inserted into the "Formal" part. 4788% 4789% Example: throwme(setter_atomic,nonzero(A)) 4790% === 4791 4792throwme(LookupPred,LookupTerm) :- 4793 findall([Location,Formal,Msg],exc_desc(LookupPred,LookupTerm,Location,Formal,Msg),Bag), 4794 length(Bag,BagLength), 4795 throwme_help(BagLength,Bag,LookupPred,LookupTerm). 4796 4797% Helper invoked if exactly 1 applicable "exception descriptor" could be found. 4798% Throw the corresponding exception! 4799% This is the first clause in line. If there is no match on arg1, the catchall 4800% fallback is used instead. 4801% The constructed error term is "quasi ISO-standard" because its structure is 4802% "error(Formal,Context)" -- but there is not guarantee that the "Formal" term 4803% is any of the ISO-listed allowed "Formal" term (in fact, it generally is not). 4804% The "Context" (about which the ISO standard says nothing, leaving it to be 4805% "implementation-defined") is structured according to SWI-Prolog conventions: 4806% "context(Location,Msg)" where "Location", if left fresh, can be filled with 4807% a stack trace on the toplevel or by a catching catch_with_backtrace/3. It 4808% is, however, often filled with the predicate indicator of the throwing 4809% predicate. The "Msg" should be a stringy thing to printed out, i.e. a 4810% human-readable explainer that is either an atom or a string. 4811% - Is there a requirement that "Msg" be forced to an atom? 4812% --- 4813 4814throwme_help(1,[[Location,Formal,Msg]],_,_) :- 4815 throw(error(Formal,context(Location,Msg))). 4816 4817% --- 4818% Helper invoked if not exactly 1 applicable "exception descriptor" could be found. 4819% That means the set of exception descriptors is incomplete/ambiguous or the lookup 4820% query is wrong. Throws a quasi-ISO-standard exception following the format 4821% error(_,_) but with the formal term the non-ISO atom 'programming_error'. 4822% - Note that "Msg" is an atom, not a string (is that ok? it should probably be 4823% a String, at least in SWI-Prolog) 4824% - Note that the second argument for error(_,_) follows SWI-Prolog conventions 4825% and with its first position fresh, may be filled with a backtrace. 4826% --- 4827 4828throwme_help(Count,_,LookupPred,LookupTerm) :- 4829 Count \== 1, 4830 with_output_to( 4831 atom(Msg), 4832 format("Instead of 1, found ~d exception descriptors for LookupPred = ~q, LookupTerm = ~q", 4833 [Count,LookupPred,LookupTerm])), 4834 throw(error(programming_error,context(_,Msg))). 4835 4836% === 4837% exc_desc(+LookupPred,+LookupTerm,?Location,?Formal,?Msg) 4838% === 4839% Descriptors for exceptions. 4840% 4841% The first two arguments are used for lookup. See throwme/2 for an explainer. 4842% 4843% The three last arguments are output values which are use to construct 4844% the exception term that is suppoed to be thrown by the caller. 4845% 4846% If "Location" is left a freshvar, it can be instantiated to a backtrack if 4847% the exception reaches the Prolog Toplevel or is caught by 4848% catch_with_backtrace/3. 4849% 4850% Otherwise, "Location" should be a predicate indicator or something similar. 4851% 4852% Example: 4853% 4854% exc_desc(jpl_call_static,no_such_method(M), 4855% jpl_call/4, 4856% existence_error(method,M), 4857% 'some text') 4858% 4859% exc_desc(jpl_call_static,no_such_method(M), 4860% _, 4861% existence_error(method,M), 4862% 'some text') 4863% 4864% The "Msg" is a user-readable message. For now, it is not dynamically 4865% constructed (i.e. using format/3 calls) inside of exc_desc/5, nor is 4866% internationalization supported for that matter. In some cases, the "Msg" 4867% has been created by caller and is passed in inside "LookupTerm", from where 4868% it is unification-picked-out-of-there into arg 5. 4869% 4870% The "Formal" is exactly the "formal term" that will used in the "exception 4871% term", and it is built by unification doing pick/put against "LookupTerm". 4872% It may or may not be ISO-Standard. 4873% 4874% Note that the fact that we adhere to ISO standard atoms instead of defining 4875% our own for JPL has the advantage that exception-printing handlers on the 4876% toplevel still work but the generated text is confusing: for example the 4877% exception-generating handler receives a "type_error" (which is meant to 4878% indicate a type problem inside a Prolog program, but here is also used to 4879% indicate a type problem of a very different nature, e.g. the caller wants 4880% to instantiate a Java interface) and the argument passed in the formal is 4881% the name of the Java class as an atom. Then the printing handler will say 4882% this: "there is a problem because this is an atom: 'foo.bar.Interface'" and 4883% only by reading the cleartext message will the actual problem be revealed: 4884% "you tried to instantiate an interface". 4885% --- 4886 4887safe_type_to_classname(Type,CN) :- 4888 catch( 4889 (jpl_type_to_classname(Type,CN) 4890 -> true 4891 ; with_output_to(atom(CN),format("~q",[Type]))), 4892 _DontCareCatcher, 4893 CN='???'). 4894 4895exc_desc(jpl_new,x_is_var, 4896 jpl_new/3, 4897 instantiation_error, 4898 '1st arg must be bound to a classname, descriptor or object type'). 4899 4900exc_desc(jpl_new,x_not_classname(X), 4901 jpl_new/3, 4902 domain_error(classname,X), 4903 'if 1st arg is an atom, it must be a classname or descriptor'). 4904 4905exc_desc(jpl_new,x_not_instantiable(X), 4906 jpl_new/3, 4907 type_error(instantiable,X), 4908 '1st arg must be a classname, descriptor or object type'). 4909 4910exc_desc(jpl_new,not_a_jpl_term(X), 4911 jpl_new/3, 4912 type_error(term,X), 4913 'result is not a org.jpl7.Term instance as required'). 4914 4915% --- 4916 4917exc_desc(jpl_new_class,params_is_var, 4918 jpl_new/3, 4919 instantiation_error, 4920 '2nd arg must be a proper list of valid parameters for a constructor'). 4921 4922exc_desc(jpl_new_class,params_is_not_list(Params), 4923 jpl_new/3, 4924 type_error(list,Params), 4925 '2nd arg must be a proper list of valid parameters for a constructor'). 4926 4927exc_desc(jpl_new_class,class_is_interface(Type), 4928 jpl_new/3, 4929 type_error(concrete_class,CN), 4930 'cannot create instance of an interface') :- safe_type_to_classname(Type,CN). 4931 4932exc_desc(jpl_new_class,class_without_constructor(Type,Arity), 4933 jpl_new/3, 4934 existence_error(constructor,CN/Arity), 4935 'no constructor found with the corresponding quantity of parameters') :- safe_type_to_classname(Type,CN). 4936 4937exc_desc(jpl_new_class,acyclic(X,Msg), 4938 jpl_new/3, 4939 type_error(acyclic,X), 4940 Msg). 4941 4942exc_desc(jpl_new_class,bad_jpl_datum(Params), 4943 jpl_new/3, 4944 domain_error(list(jpl_datum),Params), 4945 'one or more of the actual parameters is not a valid representation of any Java value or object'). 4946 4947exc_desc(jpl_new_class,single_constructor_mismatch(Co), 4948 jpl_new/3, 4949 existence_error(constructor,Co), 4950 'the actual parameters are not assignable to the formal parameter types of the only constructor which takes this qty of parameters'). 4951 4952exc_desc(jpl_new_class,any_constructor_mismatch(Params), 4953 jpl_new/3, 4954 type_error(constructor_args,Params), 4955 'the actual parameters are not assignable to the formal parameter types of any of the constructors which take this qty of parameters'). 4956 4957exc_desc(jpl_new_class,constructor_multimatch(Params), 4958 jpl_new/3, 4959 type_error(constructor_params,Params), 4960 'more than one most-specific matching constructor (shouldn''t happen)'). 4961 4962exc_desc(jpl_new_class,class_is_abstract(Type), 4963 jpl_new/3, 4964 type_error(concrete_class,CN), 4965 'cannot create instance of an abstract class') :- safe_type_to_classname(Type,CN). 4966 4967% --- 4968 4969exc_desc(jpl_new_array,params_is_var, 4970 jpl_new/3, 4971 instantiation_error, 4972 'when constructing a new array, 2nd arg must either be a non-negative integer (denoting the required array length) or a proper list of valid element values'). 4973 4974exc_desc(jpl_new_array,params_is_negative(Params), 4975 jpl_new/3, 4976 domain_error(array_length,Params), 4977 'when constructing a new array, if the 2nd arg is an integer (denoting the required array length) then it must be non-negative'). 4978 4979% --- 4980 4981exc_desc(jpl_new_primitive,primitive_type_requested(T), 4982 jpl_new/3, 4983 domain_error(object_type,T), 4984 'cannot construct an instance of a primitive type'). 4985 4986% the call to this is commented out in jpl.pl 4987exc_desc(jpl_new_primitive,params_is_var, 4988 jpl_new/3, 4989 instantiation_error, 4990 'when constructing a new instance of a primitive type, 2nd arg must be bound (to a representation of a suitable value)'). 4991 4992% the call to this is commented out in jpl.pl 4993exc_desc(jpl_new_primitive,params_is_bad(Params), 4994 jpl_new/3, 4995 domain_error(constructor_args,Params),Msg) :- 4996 atomic_list_concat([ 4997 'when constructing a new instance of a primitive type, 2nd arg must either be an ', 4998 'empty list (indicating that the default value of that type is required) or a ', 4999 'list containing exactly one representation of a suitable value'],Msg). 5000 5001% --- 5002 5003exc_desc(jpl_new_catchall,catchall(T), 5004 jpl_new/3, 5005 domain_error(jpl_type,T), 5006 '1st arg must denote a known or plausible type'). 5007 5008% --- 5009 5010exc_desc(jpl_call,arg1_is_var, 5011 jpl_call/4, 5012 instantiation_error, 5013 '1st arg must be bound to an object, classname, descriptor or type'). 5014 5015exc_desc(jpl_call,no_such_class(X), 5016 jpl_call/4, 5017 existence_error(class,X), 5018 'the named class cannot be found'). 5019 5020exc_desc(jpl_call,arg1_is_bad(X), 5021 jpl_call/4, 5022 type_error(class_name_or_descriptor,X), 5023 '1st arg must be an object, classname, descriptor or type'). 5024 5025exc_desc(jpl_call,arg1_is_array(X), 5026 jpl_call/4, 5027 type_error(object_or_class,X), 5028 'cannot call a static method of an array type, as none exists'). 5029 5030exc_desc(jpl_call,arg1_is_bad_2(X), 5031 jpl_call/4, 5032 domain_error(object_or_class,X), 5033 '1st arg must be an object, classname, descriptor or type'). 5034 5035exc_desc(jpl_call,mspec_is_var, 5036 jpl_call/4, 5037 instantiation_error, 5038 '2nd arg must be an atom naming a public method of the class or object'). 5039 5040exc_desc(jpl_call,mspec_is_bad(Mspec), 5041 jpl_call/4, 5042 type_error(method_name,Mspec), 5043 '2nd arg must be an atom naming a public method of the class or object'). 5044 5045exc_desc(jpl_call,acyclic(Te,Msg), 5046 jpl_call/4, 5047 type_error(acyclic,Te), 5048 Msg). 5049 5050exc_desc(jpl_call,nonconvertible_params(Params), 5051 jpl_call/4, 5052 type_error(method_params,Params), 5053 'not all actual parameters are convertible to Java values or references'). 5054 5055exc_desc(jpl_call,arg3_is_var, 5056 jpl_call/4, 5057 instantiation_error, 5058 '3rd arg must be a proper list of actual parameters for the named method'). 5059 5060exc_desc(jpl_call,arg3_is_bad(Params), 5061 jpl_call/4, 5062 type_error(method_params,Params), 5063 '3rd arg must be a proper list of actual parameters for the named method'). 5064 5065exc_desc(jpl_call,not_a_jpl_term(X), 5066 jpl_call/4, 5067 type_error(jni_jref,X), 5068 'result is not a org.jpl7.Term instance as required'). 5069 5070% --- 5071 5072exc_desc(jpl_call_instance,no_such_method(M), 5073 jpl_call/4, 5074 existence_error(method,M), 5075 'the class or object has no public methods with the given name and quantity of parameters'). 5076 5077exc_desc(jpl_call_instance,param_not_assignable(P), 5078 jpl_call/4, 5079 type_error(method_params,P), 5080 'the actual parameters are not assignable to the formal parameters of any of the named methods'). 5081 5082exc_desc(jpl_call_instance,multiple_most_specific(M), 5083 jpl_call/4, 5084 existence_error(most_specific_method,M), 5085 'more than one most-specific method is found for the actual parameters (this should not happen)'). 5086 5087% --- 5088 5089exc_desc(jpl_call_static,no_such_method(M), 5090 jpl_call/4, 5091 existence_error(method,M), 5092 'the class has no public static methods with the given name and quantity of parameters'). 5093 5094exc_desc(jpl_call_static,param_not_assignable(P), 5095 jpl_call/4, 5096 type_error(method_params,P), 5097 'the actual parameters are not assignable to the formal parameters of any of the named methods'). 5098 5099exc_desc(jpl_call_static,multiple_most_specific(M), 5100 jpl_call/4, 5101 existence_error(most_specific_method,M), 5102 'more than one most-specific method is found for the actual parameters (this should not happen)'). 5103 5104% --- 5105 5106exc_desc(jpl_get,arg1_is_var, 5107 jpl_get/3, 5108 instantiation_error, 5109 '1st arg must be bound to an object, classname, descriptor or type'). 5110 5111exc_desc(jpl_get,named_class_not_found(Type), 5112 jpl_get/3, 5113 existence_error(class,CN), 5114 'the named class cannot be found') :- safe_type_to_classname(Type,CN). 5115 5116exc_desc(jpl_get,arg1_is_bad(X), 5117 jpl_get/3, 5118 type_error(class_name_or_descriptor,X), 5119 '1st arg must be an object, classname, descriptor or type'). 5120 5121exc_desc(jpl_get,arg1_is_bad_2(X), 5122 jpl_get/3, 5123 domain_error(object_or_class,X), 5124 '1st arg must be an object, classname, descriptor or type'). 5125 5126exc_desc(jpl_get,not_a_jpl_term(X), 5127 jpl_get/3, 5128 type_error(jni_ref,X), 5129 'result is not a org.jpl7.Term instance as required'). 5130 5131% --- 5132 5133exc_desc(jpl_get_static,arg2_is_var, 5134 jpl_get/3, 5135 instantiation_error, 5136 '2nd arg must be bound to an atom naming a public field of the class'). 5137 5138exc_desc(jpl_get_static,arg2_is_bad(F), 5139 jpl_get/3, 5140 type_error(field_name,F), 5141 '2nd arg must be an atom naming a public field of the class'). 5142 5143exc_desc(jpl_get_static,no_such_field(F), 5144 jpl_get/3, 5145 existence_error(field,F), 5146 'the class or object has no public static field with the given name'). 5147 5148exc_desc(jpl_get_static,multiple_fields(F), 5149 jpl_get/3, 5150 existence_error(unique_field,F), 5151 'more than one field is found with the given name'). 5152 5153% --- 5154 5155exc_desc(jpl_get_instance,arg2_is_var, 5156 jpl_get/3, 5157 instantiation_error, 5158 '2nd arg must be bound to an atom naming a public field of the class or object'). 5159 5160exc_desc(jpl_get_instance,arg2_is_bad(X), 5161 jpl_get/3, 5162 type_error(field_name,X), 5163 '2nd arg must be an atom naming a public field of the class or object'). 5164 5165exc_desc(jpl_get_instance,no_such_field(Fname), 5166 jpl_get/3, 5167 existence_error(field,Fname), 5168 'the class or object has no public field with the given name'). 5169 5170exc_desc(jpl_get_instance,multiple_fields(Fname), 5171 jpl_get/3, 5172 existence_error(unique_field,Fname), 5173 'more than one field is found with the given name'). 5174 5175% --- 5176 5177exc_desc(jpl_get_instance_array,arg2_is_var, 5178 jpl_get/3, 5179 instantiation_error, 5180 'when 1st arg is an array, 2nd arg must be bound to an index, an index range, or ''length'''). 5181 5182exc_desc(jpl_get_instance_array,arg2_is_bad(X), 5183 jpl_get/3, 5184 domain_error(array_index,X), 5185 'when 1st arg is an array, integral 2nd arg must be non-negative'). 5186 5187exc_desc(jpl_get_instance_array,arg2_is_too_large(X), 5188 jpl_get/3, 5189 domain_error(array_index,X), 5190 'when 1st arg is an array, integral 2nd arg must not exceed upper bound of array'). 5191 5192exc_desc(jpl_get_instance_array,bad_range_low(R), 5193 jpl_get/3, 5194 domain_error(array_index_range,R), 5195 'lower bound of array index range must not exceed upper bound of array'). 5196 5197exc_desc(jpl_get_instance_array,bad_range_high(R), 5198 jpl_get/3, 5199 domain_error(array_index_range,R), 5200 'upper bound of array index range must not exceed upper bound of array'). 5201 5202exc_desc(jpl_get_instance_array,bad_range_pair_values(R), 5203 jpl_get/3, 5204 domain_error(array_index_range,R), 5205 'array index range must be a non-decreasing pair of non-negative integers'). 5206 5207exc_desc(jpl_get_instance_array,bad_range_pair_types(R), 5208 jpl_get/3, 5209 type_error(array_index_range,R), 5210 'array index range must be a non-decreasing pair of non-negative integers'). 5211 5212exc_desc(jpl_get_instance_array,no_such_field(F), 5213 jpl_get/3, 5214 domain_error(array_field_name,F), 5215 'the array has no public field with the given name'). 5216 5217exc_desc(jpl_get_instance_array,wrong_spec(F), 5218 jpl_get/3, 5219 type_error(array_lookup_spec,F), 5220 'when 1st arg is an array, 2nd arg must be an index, an index range, or ''length'''). 5221 5222% --- 5223 5224exc_desc(jpl_set,arg1_is_var, 5225 jpl_set/3, 5226 instantiation_error, 5227 '1st arg must be an object, classname, descriptor or type'). 5228 5229exc_desc(jpl_set,classname_does_not_resolve(X), 5230 jpl_set/3, 5231 existence_error(class,X), 5232 'the named class cannot be found'). 5233 5234exc_desc(jpl_set,named_class_not_found(Type), 5235 jpl_set/3, 5236 existence_error(class,CN), 5237 'the named class cannot be found') :- safe_type_to_classname(Type,CN). 5238 5239exc_desc(jpl_set,acyclic(X,Msg), 5240 jpl_set/3, 5241 type_error(acyclic,X), 5242 Msg). 5243 5244exc_desc(jpl_set,arg1_is_bad(X), 5245 jpl_set/3, 5246 domain_error(object_or_class,X), 5247 '1st arg must be an object, classname, descriptor or type'). 5248 5249% --- 5250 5251exc_desc(jpl_set_instance_class,arg2_is_var, 5252 jpl_set/3, 5253 instantiation_error, 5254 '2nd arg must be bound to the name of a public, non-final field'). 5255 5256exc_desc(jpl_set_instance_class,arg2_is_bad(Fname), 5257 jpl_set/3, 5258 type_error(field_name,Fname), 5259 '2nd arg must be the name of a public, non-final field'). 5260 5261exc_desc(jpl_set_instance_class,no_such_field(Fname), 5262 jpl_set/3, 5263 existence_error(field,Fname), 5264 'no public fields of the object have this name'). 5265 5266exc_desc(jpl_set_instance_class,field_is_final(Fname), 5267 jpl_set/3, 5268 permission_error(modify,final_field,Fname), 5269 'cannot assign a value to a final field (actually you could but I''ve decided not to let you)'). 5270 5271exc_desc(jpl_set_instance_class,incompatible_value(Type,V), 5272 jpl_set/3, 5273 type_error(CN,V), 5274 'the value is not assignable to the named field of the class') :- safe_type_to_classname(Type,CN). 5275 5276exc_desc(jpl_set_instance_class,arg3_is_bad(V), 5277 jpl_set/3, 5278 type_error(field_value,V), 5279 '3rd arg does not represent any Java value or object'). 5280 5281exc_desc(jpl_set_instance_class,multiple_fields(Fname), 5282 jpl_set/3, 5283 existence_error(field,Fname), 5284 'more than one public field of the object has this name (this should not happen)'). 5285 5286% --- 5287 5288exc_desc(jpl_set_instance_array,arg3_is_var, 5289 jpl_set/3, 5290 instantiation_error, 5291 'when 1st arg is an array, 3rd arg must be bound to a suitable element value or list of values'). 5292 5293exc_desc(jpl_set_instance_array,arg2_is_var, 5294 jpl_set/3, 5295 instantiation_error, 5296 'when 1st arg is an array, 2nd arg must be bound to an index or index range'). 5297 5298exc_desc(jpl_set_instance_array,arg2_is_bad(FSpec), 5299 jpl_set/3, 5300 domain_error(array_index,FSpec), 5301 'when 1st arg is an array, an integral 2nd arg must be a non-negative index'). 5302 5303exc_desc(jpl_set_instance_array,no_values(Fspec,Vs), 5304 jpl_set/3, 5305 domain_error(array_element(Fspec),Vs), 5306 'no values for array element assignment: needs one'). 5307 5308exc_desc(jpl_set_instance_array,more_than_one_value(Fspec,Vs), 5309 jpl_set/3, 5310 domain_error(array_element(Fspec),Vs), 5311 'too many values for array element assignment: needs one'). 5312 5313exc_desc(jpl_set_instance_array,too_few_values(N-M,Vs), 5314 jpl_set/3, 5315 domain_error(array_elements(N-M),Vs), 5316 'too few values for array range assignment'). 5317 5318exc_desc(jpl_set_instance_array,too_many_values(N-M,Vs), 5319 jpl_set/3, 5320 domain_error(array_elements(N-M),Vs), 5321 'too many values for array range assignment'). 5322 5323exc_desc(jpl_set_instance_array,bad_range_pair_values(N-M), 5324 jpl_set/3, 5325 domain_error(array_index_range,N-M), 5326 'array index range must be a non-decreasing pair of non-negative integers'). 5327 5328exc_desc(jpl_set_instance_array,bad_range_pair_types(N-M), 5329 jpl_set/3, 5330 type_error(array_index_range,N-M), 5331 'array index range must be a non-decreasing pair of non-negative integers'). 5332 5333exc_desc(jpl_set_instance_array,cannot_assign_to_final_field, 5334 jpl_set/3, 5335 permission_error(modify,final_field,length), 5336 'cannot assign a value to a final field'). 5337 5338exc_desc(jpl_set_instance_array,no_such_field(Fspec), 5339 jpl_set/3, 5340 existence_error(field,Fspec), 5341 'array has no field with that name'). 5342 5343exc_desc(jpl_set_instance_array,arg2_is_bad_2(Fspec), 5344 jpl_set/3, 5345 domain_error(array_index,Fspec), 5346 'when 1st arg is an array object, 2nd arg must be a non-negative index or index range'). 5347 5348% --- 5349 5350exc_desc(jpl_set_static,arg2_is_unbound, 5351 jpl_set/3, 5352 instantiation_error, 5353 'when 1st arg denotes a class, 2nd arg must be bound to the name of a public, static, non-final field'). 5354 5355exc_desc(jpl_set_static,arg2_is_bad(Fname), 5356 jpl_set/3, 5357 type_error(field_name,Fname), 5358 'when 1st arg denotes a class, 2nd arg must be the name of a public, static, non-final field'). 5359 5360exc_desc(jpl_set_static,no_such_public_static_field(field,Fname), 5361 jpl_set/3, 5362 existence_error(field,Fname), 5363 'class has no public static fields of this name'). 5364 5365exc_desc(jpl_set_static,cannot_assign_final_field(Fname), 5366 jpl_set/3, 5367 permission_error(modify,final_field,Fname), 5368 'cannot assign a value to a final field'). 5369 5370exc_desc(jpl_set_static,value_not_assignable(Type,V), 5371 jpl_set/3, 5372 type_error(CN,V), 5373 'the value is not assignable to the named field of the class') :- safe_type_to_classname(Type,CN). 5374 5375exc_desc(jpl_set_static,arg3_is_bad(field_value,V), 5376 jpl_set/3, 5377 type_error(field_value,V), 5378 '3rd arg does not represent any Java value or object'). 5379 5380exc_desc(jpl_set_static,multiple_matches(field,Fname), 5381 jpl_set/3, 5382 existence_error(field,Fname), 5383 'more than one public static field of the class has this name (this should not happen)(?)'). 5384 5385% --- 5386 5387exc_desc(jpl_set_array,not_all_values_assignable(T,Ds), 5388 jpl_set/3, 5389 type_error(array(T),Ds), 5390 'not all values are assignable to the array element type'). 5391 5392exc_desc(jpl_set_array,not_all_values_convertible(T,Ds), 5393 jpl_set/3, 5394 type_error(array(T),Ds), 5395 'not all values are convertible to Java values or references'). 5396 5397exc_desc(jpl_set_array,element_type_unknown(array_element_type,T), 5398 jpl_set/3, 5399 type_error(array_element_type,T), 5400 'array element type is unknown: neither a class, nor an array type, nor a primitive type'). 5401 5402% --- 5403 5404exc_desc(jpl_datum_to_type,is_cyclic(Term), 5405 jpl_call/4, % I don't know why, but the tests expect jpl_call/4 here 5406 type_error(acyclic,Term), 5407 'must be acyclic'). 5408 5409% --- 5410 5411exc_desc(jpl_type_to_class,arg1_is_var, 5412 jpl_type_to_class/2, 5413 instantiation_error, 5414 '1st arg must be bound to a JPL type'). 5415 5416% --- 5417 5418exc_desc(check_lib,lib_not_found(Name,Msg), 5419 check_lib/2, 5420 existence_error(library,Name), 5421 Msg). 5422 5423 5424 /******************************* 5425 * Initialize JVM * 5426 *******************************/ 5427 5428:- initialization(setup_jvm, now). % must be ready before export
A Java interface for SWI Prolog 7.x
The library(jpl) provides a bidirectional interface to a Java Virtual Machine.