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:- use_module(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)). 4057:- use_module(library(shlib), [win_add_dll_directory/1]). 4058extend_dll_search_path(Dir) :- 4059 win_add_dll_directory(Dir), 4060 ( current_prolog_flag(wine_version, _) 4061 -> prolog_to_os_filename(Dir, OSDir), 4062 ( getenv('PATH', Path0) 4063 -> atomic_list_concat([Path0, OSDir], ';', Path), 4064 setenv('PATH', Path) 4065 ; setenv('PATH', OSDir) 4066 ) 4067 ; true 4068 ). 4069:- endif.
-Djava.library.path
init
options.
4076extend_java_library_path(OsDir) :-
4077 jpl_get_default_jvm_opts(Opts0),
4078 ( select(PathOpt0, Opts0, Rest),
4079 sub_atom(PathOpt0, 0, _, _, '-Djava.library.path=')
4080 -> search_path_separator(Separator),
4081 atomic_list_concat([PathOpt0, Separator, OsDir], PathOpt),
4082 NewOpts = [PathOpt|Rest]
4083 ; atom_concat('-Djava.library.path=', OsDir, PathOpt),
4084 NewOpts = [PathOpt|Opts0]
4085 ),
4086 debug(jpl(path), 'Setting Java options to ~p', [NewOpts]),
4087 jpl_set_default_jvm_opts(NewOpts).
4094java_dirs --> 4095 % JDK directories 4096 java_dir(jvm, '/jre/bin/client'), 4097 java_dir(jvm, '/jre/bin/server'), 4098 java_dir(java, '/jre/bin'), 4099 % JRE directories 4100 java_dir(jvm, '/bin/client'), 4101 java_dir(jvm, '/bin/server'), 4102 java_dir(java, '/bin'). 4103 4104java_dir(DLL, _SubPath) --> 4105 { check_shared_object(DLL, _, _Var, Abs), 4106 Abs \== (-) 4107 }, 4108 !. 4109java_dir(_DLL, SubPath) --> 4110 { java_home(JavaHome), 4111 atom_concat(JavaHome, SubPath, SubDir), 4112 exists_directory(SubDir) 4113 }, 4114 !, 4115 [SubDir]. 4116java_dir(_, _) --> [].
4125java_home_win_key( 4126 jdk, 4127 'HKEY_LOCAL_MACHINE/Software/JavaSoft/JDK'). % new style 4128java_home_win_key( 4129 jdk, 4130 'HKEY_LOCAL_MACHINE/Software/JavaSoft/Java Development Kit'). 4131java_home_win_key( 4132 jre, 4133 'HKEY_LOCAL_MACHINE/Software/JavaSoft/JRE'). 4134java_home_win_key( 4135 jre, 4136 'HKEY_LOCAL_MACHINE/Software/JavaSoft/Java Runtime Environment'). 4137 4138java_home(Home) :- 4139 getenv('JAVA_HOME', Home), 4140 exists_directory(Home), 4141 !. 4142:- if(current_prolog_flag(windows, true)). 4143java_home(Home) :- 4144 java_home_win_key(_, Key0), % TBD: user can't choose jre or jdk 4145 catch(win_registry_get_value(Key0, 'CurrentVersion', Version), _, fail), 4146 atomic_list_concat([Key0, Version], /, Key), 4147 win_registry_get_value(Key, 'JavaHome', WinHome), 4148 prolog_to_os_filename(Home, WinHome), 4149 exists_directory(Home), 4150 !. 4151:- else. 4152java_home(Home) :- 4153 member(Home, [ '/usr/lib/java', 4154 '/usr/local/lib/java' 4155 ]), 4156 exists_directory(Home), 4157 !. 4158:- endif. 4159 4160:- dynamic 4161 jvm_ready/0. 4162:- volatile 4163 jvm_ready/0. 4164 4165setup_jvm :- 4166 jvm_ready, 4167 !. 4168setup_jvm :- 4169 add_jpl_to_classpath, 4170 add_java_to_ldpath, 4171 libjpl(JPL), 4172 catch(load_foreign_library(JPL), E, report_java_setup_problem(E)), 4173 add_jpl_to_ldpath(JPL), 4174 assert(jvm_ready). 4175 4176report_java_setup_problem(E) :- 4177 print_message(error, E), 4178 check_java_environment. 4179 4180 /******************************* 4181 * MESSAGES * 4182 *******************************/ 4183 4184:- multifile 4185 prolog:message//1. 4186 4187prologmessage(extend_ld_path(Dirs)) --> 4188 [ 'Extended DLL search path with'-[] ], 4189 dir_per_line(Dirs). 4190prologmessage(jpl(run(Command))) --> 4191 [ 'Could not find libjpl.dylib dependencies.'-[], 4192 'Please run `?- ~p.` to correct this'-[Command] 4193 ]. 4194 4195dir_per_line([]) --> []. 4196dir_per_line([H|T]) --> 4197 [ nl, ' ~q'-[H] ], 4198 dir_per_line(T). 4199 4200 /**************************************************************************** 4201 * PARSING/GENERATING ENTITY NAME / FINDCLASS DESCRIPTOR / METHOD DESCRIPTOR * 4202 ****************************************************************************/ 4203 4204% === 4205% PRINCIPLE 4206% 4207% We process list of character codes in the DCG (as opposed to lists of 4208% characters) 4209% 4210% In SWI Prolog the character codes are the Unicode code values - the DCGs 4211% looking at individual characters of a Java identifier expect this. 4212% 4213% To generate list of character codes from literals, the backquote notation 4214% can be used: 4215% 4216% ?- X=`alpha`. 4217% X = [97, 108, 112, 104, 97]. 4218% 4219% However, Jab Wielmaker says: 4220% 4221% "Please use "string" for terminals in DCGs. The SWI-Prolog DCG compiler 4222% handles these correctly and this retains compatibility." 4223% 4224% So we do that. 4225% === 4226 4227% jpl_entityname//1 4228% 4229% Relate a Java-side "entity name" (a String as returned by Class.getName()) 4230% (in the DCG accumulator as a list of Unicode code values) to JPL's 4231% Prolog-side "type term". 4232% 4233% For example: 4234% 4235% ~~~ 4236% Java-side "entity name" <-----> JPL Prolog-side "type term" 4237% "java.util.Date" class([java,util],['Date']) 4238% ~~~ 4239% 4240% @see https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Class.html#getName() 4241% 4242% Example for getName() calls generating entity names 4243% 4244% ~~~ 4245% 4246% class TJ { 4247% public static final void main(String[] argv) { 4248% 4249% System.out.println(void.class.getName()); // void 4250% System.out.println(Void.TYPE.getName()); // void 4251% System.out.println(Void.class.getName()); // java.lang.Void 4252% 4253% System.out.println(char.class.getName()); // char 4254% System.out.println(Character.TYPE.getName()); // char 4255% System.out.println(Character.class.getName()); // java.lang.Character 4256% System.out.println(Character.valueOf('x').getClass().getName()); // java.lang.Character 4257% 4258% System.out.println(int[].class.getName()); // [I 4259% System.out.println((new int[4]).getClass().getName()); // [I 4260% int[] a = {1,2,3}; System.out.println(a.getClass().getName()); // [I 4261% 4262% System.out.println(int[][].class.getName()); // [[I 4263% System.out.println((new int[4][4]).getClass().getName()); // [[I 4264% int[][] aa = {{1},{2},{3}}; System.out.println(aa.getClass().getName()); // [[I 4265% 4266% System.out.println(Integer[][].class.getName()); // [[Ljava.lang.Integer; 4267% System.out.println((new Integer[4][4]).getClass().getName()); // [[Ljava.lang.Integer; 4268% Integer[][] bb = {{1},{2},{3}}; System.out.println(bb.getClass().getName()); // [[Ljava.lang.Integer; 4269% 4270% } 4271% } 4272% ~~~ 4273% 4274% Note that We can list the possible "jpl type terms" directly in the head of 4275% jpl_entityname//1 (except for the primitives). This helps in clause selection 4276% and documentation. Note that the fact that the last two clauses T are not tagged as 4277% "primitive()" makes this representation nonuniform; should be fixed at some time. 4278% --- 4279 4280jpl_entityname(class(Ps,Cs)) --> jpl_classname(class(Ps,Cs),dotty),!. 4281jpl_entityname(array(T)) --> jpl_array_type_descriptor(array(T),dotty),!. 4282jpl_entityname(void) --> "void",!. 4283jpl_entityname(P) --> jpl_primitive_entityname(P). 4284 4285% --- 4286% The "findclass descriptor" is used for the JNI function FindClass and is 4287% either an array type descriptor with a "slashy" package name or directly 4288% a classname, also with a "slasgy" package name 4289% --- 4290 4291jpl_findclass_descriptor(array(T)) --> jpl_array_type_descriptor(array(T),slashy),!. 4292jpl_findclass_descriptor(class(Ps,Cs)) --> jpl_classname(class(Ps,Cs),slashy). 4293 4294% --- 4295% The "method descriptor" is used to find a method ID based on the method 4296% signature. It contains method arguments and type of method return value 4297% --- 4298 4299jpl_method_descriptor(method(Ts,T)) --> "(", jpl_method_descriptor_args(Ts), ")", jpl_method_descriptor_retval(T). 4300 4301jpl_method_descriptor_args([T|Ts]) --> jpl_field_descriptor(T,slashy), !, jpl_method_descriptor_args(Ts). 4302jpl_method_descriptor_args([]) --> []. 4303 4304jpl_method_descriptor_retval(void) --> "V". 4305jpl_method_descriptor_retval(T) --> jpl_field_descriptor(T,slashy). 4306 4307% --- 4308% The "binary classname" (i.e. the classname as it appears in binaries) as 4309% specified in The "Java Language Specification". 4310% See "Binary Compatibility" - "The Form of a Binary" 4311% https://docs.oracle.com/javase/specs/jls/se14/html/jls-13.html#jls-13.1 4312% which points to the "fully qualified name" and "canonical name" 4313% https://docs.oracle.com/javase/specs/jls/se14/html/jls-6.html#jls-6.7 4314% 4315% For JNI, we can switch to "slashy" mode instead of the "dotty" mode, which 4316% technically makes this NOT the "binary classname", but we keep the predicate name. 4317% --- 4318 4319jpl_classname(class(Ps,Cs),Mode) --> jpl_package_parts(Ps,Mode), jpl_class_parts(Cs). 4320 4321% --- 4322% The qualified name of the package (which may be empty if it is the 4323% unnamed package). This is a series of Java identifiers separated by dots, but 4324% in order to reduce codesize, we switch to the "slash" separator depending 4325% on a second argument, the mode, which is either "dotty" or "slashy". 4326% "The fully qualified name of a named package that is not a subpackage of a 4327% named package is its simple name." ... "A simple name is a single identifier." 4328% https://docs.oracle.com/javase/specs/jls/se14/html/jls-6.html#jls-6.7 4329% Note that the last '.' is not considered a separator towards the subsequent 4330% class parts but as a terminator of the package parts sequence (it's a view 4331% less demanding of backtracking) 4332% --- 4333 4334jpl_package_parts([A|As],dotty) --> jpl_java_id(A), ".", !, jpl_package_parts(As,dotty). 4335jpl_package_parts([A|As],slashy) --> jpl_java_id(A), "/", !, jpl_package_parts(As,slashy). 4336jpl_package_parts([],_) --> []. 4337 4338% --- 4339% The class parts of a class name (everything beyond the last dot 4340% of the package prefix, if it exists). This comes from "13.1 - The form of 4341% a binary", where it is laid out a bit confusingly. 4342% https://docs.oracle.com/javase/specs/jls/se14/html/jls-13.html#jls-13.1 4343% 4344% PROBLEM 2020-08: 4345% 4346% Here is an ambiguity that I haven't been able to resolve: '$' is a perfectly 4347% legitimate character both at the start and in the middle of a classname, 4348% in fact you can create classes with '$' inside the classname and they compile 4349% marvelously (try it!). However it is also used as separator for inner class 4350% names ... but not really! In fact, it is just a concatentation character for 4351% a _generated class name_ (that makes sense - an inner class is a syntactic 4352% construct of Java the Language, but of no concern to the JVM, not even for 4353% access checking because the compiler is supposed to have bleached out any 4354% problemtic code). 4355% Parsing such a generated class name can go south in several different ways: 4356% '$' at the begging, '$' at the end, multiple runs of '$$$' .. one should not 4357% attempt to do it! 4358% But the original JPL code does, so we keep this practice for now. 4359% --- 4360 4361jpl_class_parts(Cs) --> { nonvar(Cs), ! }, % guard 4362 { atomic_list_concat(Cs,'$',A) }, % fuse known Cs with '$' 4363 jpl_java_type_id(A). % verify it & insert it into list 4364 4365jpl_class_parts(Cs) --> { var(Cs), ! }, % guard 4366 jpl_java_type_id(A), % grab an id including its '$' 4367 { messy_dollar_split(A,Cs) }. % split it along '$' 4368 4369 4370% --- 4371% "field descriptors" appear in method signatures or inside array type 4372% descriptors (which are itself field descriptors) 4373% --- 4374 4375jpl_field_descriptor(class(Ps,Cs),Mode) --> jpl_reference_type_descriptor(class(Ps,Cs),Mode),!. 4376jpl_field_descriptor(array(T),Mode) --> jpl_array_type_descriptor(array(T),Mode),!. 4377jpl_field_descriptor(T,_) --> jpl_primitive_type_descriptor(T). % sadly untagged with primitive(_) in the head 4378 4379jpl_reference_type_descriptor(class(Ps,Cs),Mode) --> "L", jpl_classname(class(Ps,Cs),Mode), ";". 4380 4381jpl_array_type_descriptor(array(T),Mode) --> "[", jpl_field_descriptor(T,Mode). 4382 4383% --- 4384% Breaking a bare classname at the '$' 4385% --- 4386% Heuristic: Only a '$' flanked to the left by a valid character 4387% that is a non-dollar and to the right by a valid character that 4388% may or may not be a dollar gives rise to split. 4389% 4390% The INVERSE of messy_dollar_split/2 is atomic_list_concat/3 4391 4392messy_dollar_split(A,Out) :- 4393 assertion(A \== ''), 4394 atom_chars(A,Chars), 4395 append([''|Chars],[''],GAChars), % GA is a "guarded A char list" flanked by empties and contains at least 3 chars 4396 triple_process(GAChars,[],[],RunsOut), 4397 postprocess_messy_dollar_split_runs(RunsOut,Out). 4398 4399postprocess_messy_dollar_split_runs(Runs,Out) :- 4400 reverse(Runs,R1), 4401 maplist([Rin,Rout]>>reverse(Rin,Rout),R1,O1), 4402 maplist([Chars,Atom]>>atom_chars(Atom,Chars),O1,Out). 4403 4404% Split only between P and N, dropping C, when: 4405% 1) C is a $ and P is not a dollar and not a start of line 4406% 2) N is not the end of line 4407 4408triple_process([P,'$',N|Rest],Run,Runs,Out) :- 4409 N \== '', P \== '$' , P \== '',!, 4410 triple_process(['',N|Rest],[],[Run|Runs],Out). 4411 4412triple_process(['','$',N|Rest],Run,Runs,Out) :- 4413 !, 4414 triple_process(['',N|Rest],['$'|Run],Runs,Out). 4415 4416triple_process([_,C,N|Rest],Run,Runs,Out) :- 4417 C \== '$',!, 4418 triple_process([C,N|Rest],[C|Run],Runs,Out). 4419 4420triple_process([_,C,''],Run,Runs,[[C|Run]|Runs]) :- !. 4421 4422triple_process([_,''],Run,Runs,[Run|Runs]). 4423 4424% === 4425% Low-level DCG rules 4426% === 4427 4428% --- 4429% A Java type identifier is a Java identifier different from "var" and "yield" 4430% --- 4431 4432jpl_java_type_id(I) --> jpl_java_id(I), { \+memberchk(I,[var,yield]) }. 4433 4434% --- 4435% The Java identifier is described at 4436% https://docs.oracle.com/javase/specs/jls/se14/html/jls-3.html#jls-Identifier 4437% --- 4438 4439jpl_java_id(I) --> jpl_java_id_raw(I), 4440 { \+jpl_java_keyword(I), 4441 \+jpl_java_boolean_literal(I), 4442 \+jpl_java_null_literal(I) }. 4443 4444% --- 4445% For direct handling of an identifier, we suffer symmetry breakdown. 4446% --- 4447 4448jpl_java_id_raw(A) --> { atom(A),! }, % guard 4449 { atom_codes(A,[C|Cs]) }, % explode A 4450 { jpl_java_id_start_char(C) }, 4451 [C], 4452 jpl_java_id_part_chars(Cs). 4453 4454% building X from the character code list 4455 4456jpl_java_id_raw(A) --> { var(A),! }, % guard 4457 [C], 4458 { jpl_java_id_start_char(C) }, 4459 jpl_java_id_part_chars(Cs), 4460 { atom_codes(A,[C|Cs]) }. % fuse A 4461 4462jpl_java_id_part_chars([C|Cs]) --> [C], { jpl_java_id_part_char(C) } ,!, jpl_java_id_part_chars(Cs). 4463jpl_java_id_part_chars([]) --> []. 4464 4465% --- 4466% jpl_primitive_in_array//1 4467% Described informally in Javadoc for Class.getName() 4468% https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Class.html#getName() 4469% The left-hand side should (the JPL type) really be tagged with primitive(boolean) etc. 4470% --- 4471 4472jpl_primitive_type_descriptor(boolean) --> "Z",!. 4473jpl_primitive_type_descriptor(byte) --> "B",!. 4474jpl_primitive_type_descriptor(char) --> "C",!. 4475jpl_primitive_type_descriptor(double) --> "D",!. 4476jpl_primitive_type_descriptor(float) --> "F",!. 4477jpl_primitive_type_descriptor(int) --> "I",!. 4478jpl_primitive_type_descriptor(long) --> "J",!. 4479jpl_primitive_type_descriptor(short) --> "S". 4480 4481% --- 4482% jpl_primitive_entityname//1 4483% These are just the primitive names. 4484% The left-hand side should (the JPL type) really be tagged with primitive(boolean) etc. 4485% --- 4486 4487jpl_primitive_entityname(boolean) --> "boolean" ,!. 4488jpl_primitive_entityname(byte) --> "byte" ,!. 4489jpl_primitive_entityname(char) --> "char" ,!. 4490jpl_primitive_entityname(double) --> "double" ,!. 4491jpl_primitive_entityname(float) --> "float" ,!. 4492jpl_primitive_entityname(int) --> "int" ,!. 4493jpl_primitive_entityname(long) --> "long" ,!. 4494jpl_primitive_entityname(short) --> "short". 4495 4496% --- 4497% Certain java keywords that may not occur as java identifier 4498% --- 4499 4500jpl_java_boolean_literal(true). 4501jpl_java_boolean_literal(false). 4502 4503jpl_java_null_literal(null). 4504 4505jpl_java_keyword('_'). 4506jpl_java_keyword(abstract). 4507jpl_java_keyword(assert). 4508jpl_java_keyword(boolean). 4509jpl_java_keyword(break). 4510jpl_java_keyword(byte). 4511jpl_java_keyword(case). 4512jpl_java_keyword(catch). 4513jpl_java_keyword(char). 4514jpl_java_keyword(class). 4515jpl_java_keyword(const). 4516jpl_java_keyword(continue). 4517jpl_java_keyword(default). 4518jpl_java_keyword(do). 4519jpl_java_keyword(double). 4520jpl_java_keyword(else). 4521jpl_java_keyword(enum). 4522jpl_java_keyword(extends). 4523jpl_java_keyword(final). 4524jpl_java_keyword(finally). 4525jpl_java_keyword(float). 4526jpl_java_keyword(for). 4527jpl_java_keyword(goto). 4528jpl_java_keyword(if). 4529jpl_java_keyword(implements). 4530jpl_java_keyword(import). 4531jpl_java_keyword(instanceof). 4532jpl_java_keyword(int). 4533jpl_java_keyword(interface). 4534jpl_java_keyword(long). 4535jpl_java_keyword(native). 4536jpl_java_keyword(new). 4537jpl_java_keyword(package). 4538jpl_java_keyword(private). 4539jpl_java_keyword(protected). 4540jpl_java_keyword(public). 4541jpl_java_keyword(return). 4542jpl_java_keyword(short). 4543jpl_java_keyword(static). 4544jpl_java_keyword(strictfp). 4545jpl_java_keyword(super). 4546jpl_java_keyword(switch). 4547jpl_java_keyword(synchronized). 4548jpl_java_keyword(this). 4549jpl_java_keyword(throw). 4550jpl_java_keyword(throws). 4551jpl_java_keyword(transient). 4552jpl_java_keyword(try). 4553jpl_java_keyword(void). 4554jpl_java_keyword(volatile). 4555jpl_java_keyword(while). 4556 4557% === 4558% Classify codepoints (i.e. integers) as "Java identifier start/part characters" 4559% 4560% A "Java identifier" starts with a "Java identifier start character" and 4561% continues with a "Java identifier part character". 4562% 4563% A "Java identifier start character" is a character for which 4564% Character.isJavaIdentifierStart(c) returns true, where "c" can be a 4565% Java char or an integer Unicode code value (basically, that's the definition). 4566% 4567% Similarly, a "Java identifier part character" is a character for which 4568% point Character.isJavaIdentifierPart(c) returns true 4569% 4570% See: 4571% 4572% https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Character.html#isJavaIdentifierStart(int) 4573% https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Character.html#isJavaIdentifierPart(int) 4574% 4575% A simple Java program was used to generate the runs of unicode character 4576% points listed below. They are searched lineraly. Generally, a 4577% code point/value encountered by jpl would be below even 255 and so be 4578% found quickly 4579% 4580% PROBLEM: 4581% 4582% 1) If the Prolog implementation does not represent characters internally 4583% with Unicode code values, i.e. if atom_codes/2 takes/returns other values 4584% than Unicode code values (may be the case for Prologs other than SWI Prolog) 4585% an implementation-dependent mapping from/to Unicode will have to be performed 4586% first! 4587% 4588% 2) Is this slow or not? It depends on what the compiler does. 4589% === 4590 4591jpl_java_id_start_char(C) :- 4592 assertion(integer(C)), 4593 java_id_start_char_ranges(Ranges), % retrieve ranges 4594 char_inside_range(C,Ranges). % check 4595 4596jpl_java_id_part_char(C) :- 4597 assertion(integer(C)), 4598 java_id_part_char_ranges(Ranges), % retrieve ranges 4599 char_inside_range(C,Ranges). % check 4600 4601char_inside_range(C,[[_Low,High]|Ranges]) :- 4602 High < C,!,char_inside_range(C,Ranges). 4603 4604char_inside_range(C,[[Low,High]|_]) :- 4605 Low =< C, C =< High. 4606 4607% --- 4608% The ranges below are generated with a Java program, then printed 4609% See "CharRangePrinter.java" 4610% Note that 36 is "$" which IS allowed as start and part character! 4611% In fact, there are class names that start with '$' (which is why the 4612% current version of JPL cannot connect to LibreOffice) 4613% --- 4614 4615java_id_start_char_ranges( 4616 [[36,36],[65,90],[95,95],[97,122],[162,165],[170,170],[181,181],[186,186], 4617 [192,214],[216,246],[248,705],[710,721],[736,740],[748,748],[750,750], 4618 [880,884],[886,887],[890,893],[895,895],[902,902],[904,906],[908,908], 4619 [910,929],[931,1013],[1015,1153],[1162,1327],[1329,1366],[1369,1369], 4620 [1376,1416],[1423,1423],[1488,1514],[1519,1522],[1547,1547],[1568,1610], 4621 [1646,1647],[1649,1747],[1749,1749],[1765,1766],[1774,1775],[1786,1788], 4622 [1791,1791],[1808,1808],[1810,1839],[1869,1957],[1969,1969],[1994,2026], 4623 [2036,2037],[2042,2042],[2046,2069],[2074,2074],[2084,2084],[2088,2088], 4624 [2112,2136],[2144,2154],[2208,2228],[2230,2237],[2308,2361],[2365,2365], 4625 [2384,2384],[2392,2401],[2417,2432],[2437,2444],[2447,2448],[2451,2472], 4626 [2474,2480],[2482,2482],[2486,2489],[2493,2493],[2510,2510],[2524,2525], 4627 [2527,2529],[2544,2547],[2555,2556],[2565,2570],[2575,2576],[2579,2600], 4628 [2602,2608],[2610,2611],[2613,2614],[2616,2617],[2649,2652],[2654,2654], 4629 [2674,2676],[2693,2701],[2703,2705],[2707,2728],[2730,2736],[2738,2739], 4630 [2741,2745],[2749,2749],[2768,2768],[2784,2785],[2801,2801],[2809,2809], 4631 [2821,2828],[2831,2832],[2835,2856],[2858,2864],[2866,2867],[2869,2873], 4632 [2877,2877],[2908,2909],[2911,2913],[2929,2929],[2947,2947],[2949,2954], 4633 [2958,2960],[2962,2965],[2969,2970],[2972,2972],[2974,2975],[2979,2980], 4634 [2984,2986],[2990,3001],[3024,3024],[3065,3065],[3077,3084],[3086,3088], 4635 [3090,3112],[3114,3129],[3133,3133],[3160,3162],[3168,3169],[3200,3200], 4636 [3205,3212],[3214,3216],[3218,3240],[3242,3251],[3253,3257],[3261,3261], 4637 [3294,3294],[3296,3297],[3313,3314],[3333,3340],[3342,3344],[3346,3386], 4638 [3389,3389],[3406,3406],[3412,3414],[3423,3425],[3450,3455],[3461,3478], 4639 [3482,3505],[3507,3515],[3517,3517],[3520,3526],[3585,3632],[3634,3635], 4640 [3647,3654],[3713,3714],[3716,3716],[3718,3722],[3724,3747],[3749,3749], 4641 [3751,3760],[3762,3763],[3773,3773],[3776,3780],[3782,3782],[3804,3807], 4642 [3840,3840],[3904,3911],[3913,3948],[3976,3980],[4096,4138],[4159,4159], 4643 [4176,4181],[4186,4189],[4193,4193],[4197,4198],[4206,4208],[4213,4225], 4644 [4238,4238],[4256,4293],[4295,4295],[4301,4301],[4304,4346],[4348,4680], 4645 [4682,4685],[4688,4694],[4696,4696],[4698,4701],[4704,4744],[4746,4749], 4646 [4752,4784],[4786,4789],[4792,4798],[4800,4800],[4802,4805],[4808,4822], 4647 [4824,4880],[4882,4885],[4888,4954],[4992,5007],[5024,5109],[5112,5117], 4648 [5121,5740],[5743,5759],[5761,5786],[5792,5866],[5870,5880],[5888,5900], 4649 [5902,5905],[5920,5937],[5952,5969],[5984,5996],[5998,6000],[6016,6067], 4650 [6103,6103],[6107,6108],[6176,6264],[6272,6276],[6279,6312],[6314,6314], 4651 [6320,6389],[6400,6430],[6480,6509],[6512,6516],[6528,6571],[6576,6601], 4652 [6656,6678],[6688,6740],[6823,6823],[6917,6963],[6981,6987],[7043,7072], 4653 [7086,7087],[7098,7141],[7168,7203],[7245,7247],[7258,7293],[7296,7304], 4654 [7312,7354],[7357,7359],[7401,7404],[7406,7411],[7413,7414],[7418,7418], 4655 [7424,7615],[7680,7957],[7960,7965],[7968,8005],[8008,8013],[8016,8023], 4656 [8025,8025],[8027,8027],[8029,8029],[8031,8061],[8064,8116],[8118,8124], 4657 [8126,8126],[8130,8132],[8134,8140],[8144,8147],[8150,8155],[8160,8172], 4658 [8178,8180],[8182,8188],[8255,8256],[8276,8276],[8305,8305],[8319,8319], 4659 [8336,8348],[8352,8383],[8450,8450],[8455,8455],[8458,8467],[8469,8469], 4660 [8473,8477],[8484,8484],[8486,8486],[8488,8488],[8490,8493],[8495,8505], 4661 [8508,8511],[8517,8521],[8526,8526],[8544,8584],[11264,11310],[11312,11358], 4662 [11360,11492],[11499,11502],[11506,11507],[11520,11557],[11559,11559], 4663 [11565,11565],[11568,11623],[11631,11631],[11648,11670],[11680,11686], 4664 [11688,11694],[11696,11702],[11704,11710],[11712,11718],[11720,11726], 4665 [11728,11734],[11736,11742],[11823,11823],[12293,12295],[12321,12329], 4666 [12337,12341],[12344,12348],[12353,12438],[12445,12447],[12449,12538], 4667 [12540,12543],[12549,12591],[12593,12686],[12704,12730],[12784,12799], 4668 [13312,19893],[19968,40943],[40960,42124],[42192,42237],[42240,42508], 4669 [42512,42527],[42538,42539],[42560,42606],[42623,42653],[42656,42735], 4670 [42775,42783],[42786,42888],[42891,42943],[42946,42950],[42999,43009], 4671 [43011,43013],[43015,43018],[43020,43042],[43064,43064],[43072,43123], 4672 [43138,43187],[43250,43255],[43259,43259],[43261,43262],[43274,43301], 4673 [43312,43334],[43360,43388],[43396,43442],[43471,43471],[43488,43492], 4674 [43494,43503],[43514,43518],[43520,43560],[43584,43586],[43588,43595], 4675 [43616,43638],[43642,43642],[43646,43695],[43697,43697],[43701,43702], 4676 [43705,43709],[43712,43712],[43714,43714],[43739,43741],[43744,43754], 4677 [43762,43764],[43777,43782],[43785,43790],[43793,43798],[43808,43814], 4678 [43816,43822],[43824,43866],[43868,43879],[43888,44002],[44032,55203], 4679 [55216,55238],[55243,55291],[63744,64109],[64112,64217],[64256,64262], 4680 [64275,64279],[64285,64285],[64287,64296],[64298,64310],[64312,64316], 4681 [64318,64318],[64320,64321],[64323,64324],[64326,64433],[64467,64829], 4682 [64848,64911],[64914,64967],[65008,65020],[65075,65076],[65101,65103], 4683 [65129,65129],[65136,65140],[65142,65276],[65284,65284],[65313,65338], 4684 [65343,65343],[65345,65370],[65382,65470],[65474,65479],[65482,65487], 4685 [65490,65495],[65498,65500],[65504,65505],[65509,65510]]). 4686 4687java_id_part_char_ranges( 4688 [[0,8],[14,27],[36,36],[48,57],[65,90],[95,95],[97,122],[127,159],[162,165], 4689 [170,170],[173,173],[181,181],[186,186],[192,214],[216,246],[248,705], 4690 [710,721],[736,740],[748,748],[750,750],[768,884],[886,887],[890,893], 4691 [895,895],[902,902],[904,906],[908,908],[910,929],[931,1013],[1015,1153], 4692 [1155,1159],[1162,1327],[1329,1366],[1369,1369],[1376,1416],[1423,1423], 4693 [1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1488,1514], 4694 [1519,1522],[1536,1541],[1547,1547],[1552,1562],[1564,1564],[1568,1641], 4695 [1646,1747],[1749,1757],[1759,1768],[1770,1788],[1791,1791],[1807,1866], 4696 [1869,1969],[1984,2037],[2042,2042],[2045,2093],[2112,2139],[2144,2154], 4697 [2208,2228],[2230,2237],[2259,2403],[2406,2415],[2417,2435],[2437,2444], 4698 [2447,2448],[2451,2472],[2474,2480],[2482,2482],[2486,2489],[2492,2500], 4699 [2503,2504],[2507,2510],[2519,2519],[2524,2525],[2527,2531],[2534,2547], 4700 [2555,2556],[2558,2558],[2561,2563],[2565,2570],[2575,2576],[2579,2600], 4701 [2602,2608],[2610,2611],[2613,2614],[2616,2617],[2620,2620],[2622,2626], 4702 [2631,2632],[2635,2637],[2641,2641],[2649,2652],[2654,2654],[2662,2677], 4703 [2689,2691],[2693,2701],[2703,2705],[2707,2728],[2730,2736],[2738,2739], 4704 [2741,2745],[2748,2757],[2759,2761],[2763,2765],[2768,2768],[2784,2787], 4705 [2790,2799],[2801,2801],[2809,2815],[2817,2819],[2821,2828],[2831,2832], 4706 [2835,2856],[2858,2864],[2866,2867],[2869,2873],[2876,2884],[2887,2888], 4707 [2891,2893],[2902,2903],[2908,2909],[2911,2915],[2918,2927],[2929,2929], 4708 [2946,2947],[2949,2954],[2958,2960],[2962,2965],[2969,2970],[2972,2972], 4709 [2974,2975],[2979,2980],[2984,2986],[2990,3001],[3006,3010],[3014,3016], 4710 [3018,3021],[3024,3024],[3031,3031],[3046,3055],[3065,3065],[3072,3084], 4711 [3086,3088],[3090,3112],[3114,3129],[3133,3140],[3142,3144],[3146,3149], 4712 [3157,3158],[3160,3162],[3168,3171],[3174,3183],[3200,3203],[3205,3212], 4713 [3214,3216],[3218,3240],[3242,3251],[3253,3257],[3260,3268],[3270,3272], 4714 [3274,3277],[3285,3286],[3294,3294],[3296,3299],[3302,3311],[3313,3314], 4715 [3328,3331],[3333,3340],[3342,3344],[3346,3396],[3398,3400],[3402,3406], 4716 [3412,3415],[3423,3427],[3430,3439],[3450,3455],[3458,3459],[3461,3478], 4717 [3482,3505],[3507,3515],[3517,3517],[3520,3526],[3530,3530],[3535,3540], 4718 [3542,3542],[3544,3551],[3558,3567],[3570,3571],[3585,3642],[3647,3662], 4719 [3664,3673],[3713,3714],[3716,3716],[3718,3722],[3724,3747],[3749,3749], 4720 [3751,3773],[3776,3780],[3782,3782],[3784,3789],[3792,3801],[3804,3807], 4721 [3840,3840],[3864,3865],[3872,3881],[3893,3893],[3895,3895],[3897,3897], 4722 [3902,3911],[3913,3948],[3953,3972],[3974,3991],[3993,4028],[4038,4038], 4723 [4096,4169],[4176,4253],[4256,4293],[4295,4295],[4301,4301],[4304,4346], 4724 [4348,4680],[4682,4685],[4688,4694],[4696,4696],[4698,4701],[4704,4744], 4725 [4746,4749],[4752,4784],[4786,4789],[4792,4798],[4800,4800],[4802,4805], 4726 [4808,4822],[4824,4880],[4882,4885],[4888,4954],[4957,4959],[4992,5007], 4727 [5024,5109],[5112,5117],[5121,5740],[5743,5759],[5761,5786],[5792,5866], 4728 [5870,5880],[5888,5900],[5902,5908],[5920,5940],[5952,5971],[5984,5996], 4729 [5998,6000],[6002,6003],[6016,6099],[6103,6103],[6107,6109],[6112,6121], 4730 [6155,6158],[6160,6169],[6176,6264],[6272,6314],[6320,6389],[6400,6430], 4731 [6432,6443],[6448,6459],[6470,6509],[6512,6516],[6528,6571],[6576,6601], 4732 [6608,6617],[6656,6683],[6688,6750],[6752,6780],[6783,6793],[6800,6809], 4733 [6823,6823],[6832,6845],[6912,6987],[6992,7001],[7019,7027],[7040,7155], 4734 [7168,7223],[7232,7241],[7245,7293],[7296,7304],[7312,7354],[7357,7359], 4735 [7376,7378],[7380,7418],[7424,7673],[7675,7957],[7960,7965],[7968,8005], 4736 [8008,8013],[8016,8023],[8025,8025],[8027,8027],[8029,8029],[8031,8061], 4737 [8064,8116],[8118,8124],[8126,8126],[8130,8132],[8134,8140],[8144,8147], 4738 [8150,8155],[8160,8172],[8178,8180],[8182,8188],[8203,8207],[8234,8238], 4739 [8255,8256],[8276,8276],[8288,8292],[8294,8303],[8305,8305],[8319,8319], 4740 [8336,8348],[8352,8383],[8400,8412],[8417,8417],[8421,8432],[8450,8450], 4741 [8455,8455],[8458,8467],[8469,8469],[8473,8477],[8484,8484],[8486,8486], 4742 [8488,8488],[8490,8493],[8495,8505],[8508,8511],[8517,8521],[8526,8526], 4743 [8544,8584],[11264,11310],[11312,11358],[11360,11492],[11499,11507], 4744 [11520,11557],[11559,11559],[11565,11565],[11568,11623],[11631,11631], 4745 [11647,11670],[11680,11686],[11688,11694],[11696,11702],[11704,11710], 4746 [11712,11718],[11720,11726],[11728,11734],[11736,11742],[11744,11775], 4747 [11823,11823],[12293,12295],[12321,12335],[12337,12341],[12344,12348], 4748 [12353,12438],[12441,12442],[12445,12447],[12449,12538],[12540,12543], 4749 [12549,12591],[12593,12686],[12704,12730],[12784,12799],[13312,19893], 4750 [19968,40943],[40960,42124],[42192,42237],[42240,42508],[42512,42539], 4751 [42560,42607],[42612,42621],[42623,42737],[42775,42783],[42786,42888], 4752 [42891,42943],[42946,42950],[42999,43047],[43064,43064],[43072,43123], 4753 [43136,43205],[43216,43225],[43232,43255],[43259,43259],[43261,43309], 4754 [43312,43347],[43360,43388],[43392,43456],[43471,43481],[43488,43518], 4755 [43520,43574],[43584,43597],[43600,43609],[43616,43638],[43642,43714], 4756 [43739,43741],[43744,43759],[43762,43766],[43777,43782],[43785,43790], 4757 [43793,43798],[43808,43814],[43816,43822],[43824,43866],[43868,43879], 4758 [43888,44010],[44012,44013],[44016,44025],[44032,55203],[55216,55238], 4759 [55243,55291],[63744,64109],[64112,64217],[64256,64262],[64275,64279], 4760 [64285,64296],[64298,64310],[64312,64316],[64318,64318],[64320,64321], 4761 [64323,64324],[64326,64433],[64467,64829],[64848,64911],[64914,64967], 4762 [65008,65020],[65024,65039],[65056,65071],[65075,65076],[65101,65103], 4763 [65129,65129],[65136,65140],[65142,65276],[65279,65279],[65284,65284], 4764 [65296,65305],[65313,65338],[65343,65343],[65345,65370],[65382,65470], 4765 [65474,65479],[65482,65487],[65490,65495],[65498,65500],[65504,65505], 4766 [65509,65510],[65529,65531]]). 4767 4768 4769 /******************************* 4770 * EXCEPTION HANDLING * 4771 *******************************/ 4772 4773% === 4774% throwme(+LookupPred,+LookupTerm) 4775% 4776% Predicate called to construct an exception term and throw it. Information 4777% about how to construct the actual exception is found by performing a lookup 4778% based on the key formed by the pair (LookupPred,LookupTerm). 4779% 4780% LookupPred : 4781% What predicate is throwing; this is an atom (a keyword) generally shaped 4782% after the actual predicate name of the throwing predicate. It is not a 4783% predicate indicator. 4784% 4785% LookupTerm : 4786% A term, possibly compound, that describes the problem somehow. It is both 4787% programmer-interpretable (but still abstract) as well as a way of passing 4788% values that can be inserted into the "Formal" part. 4789% 4790% Example: throwme(setter_atomic,nonzero(A)) 4791% === 4792 4793throwme(LookupPred,LookupTerm) :- 4794 findall([Location,Formal,Msg],exc_desc(LookupPred,LookupTerm,Location,Formal,Msg),Bag), 4795 length(Bag,BagLength), 4796 throwme_help(BagLength,Bag,LookupPred,LookupTerm). 4797 4798% Helper invoked if exactly 1 applicable "exception descriptor" could be found. 4799% Throw the corresponding exception! 4800% This is the first clause in line. If there is no match on arg1, the catchall 4801% fallback is used instead. 4802% The constructed error term is "quasi ISO-standard" because its structure is 4803% "error(Formal,Context)" -- but there is not guarantee that the "Formal" term 4804% is any of the ISO-listed allowed "Formal" term (in fact, it generally is not). 4805% The "Context" (about which the ISO standard says nothing, leaving it to be 4806% "implementation-defined") is structured according to SWI-Prolog conventions: 4807% "context(Location,Msg)" where "Location", if left fresh, can be filled with 4808% a stack trace on the toplevel or by a catching catch_with_backtrace/3. It 4809% is, however, often filled with the predicate indicator of the throwing 4810% predicate. The "Msg" should be a stringy thing to printed out, i.e. a 4811% human-readable explainer that is either an atom or a string. 4812% - Is there a requirement that "Msg" be forced to an atom? 4813% --- 4814 4815throwme_help(1,[[Location,Formal,Msg]],_,_) :- 4816 throw(error(Formal,context(Location,Msg))). 4817 4818% --- 4819% Helper invoked if not exactly 1 applicable "exception descriptor" could be found. 4820% That means the set of exception descriptors is incomplete/ambiguous or the lookup 4821% query is wrong. Throws a quasi-ISO-standard exception following the format 4822% error(_,_) but with the formal term the non-ISO atom 'programming_error'. 4823% - Note that "Msg" is an atom, not a string (is that ok? it should probably be 4824% a String, at least in SWI-Prolog) 4825% - Note that the second argument for error(_,_) follows SWI-Prolog conventions 4826% and with its first position fresh, may be filled with a backtrace. 4827% --- 4828 4829throwme_help(Count,_,LookupPred,LookupTerm) :- 4830 Count \== 1, 4831 with_output_to( 4832 atom(Msg), 4833 format("Instead of 1, found ~d exception descriptors for LookupPred = ~q, LookupTerm = ~q", 4834 [Count,LookupPred,LookupTerm])), 4835 throw(error(programming_error,context(_,Msg))). 4836 4837% === 4838% exc_desc(+LookupPred,+LookupTerm,?Location,?Formal,?Msg) 4839% === 4840% Descriptors for exceptions. 4841% 4842% The first two arguments are used for lookup. See throwme/2 for an explainer. 4843% 4844% The three last arguments are output values which are use to construct 4845% the exception term that is suppoed to be thrown by the caller. 4846% 4847% If "Location" is left a freshvar, it can be instantiated to a backtrack if 4848% the exception reaches the Prolog Toplevel or is caught by 4849% catch_with_backtrace/3. 4850% 4851% Otherwise, "Location" should be a predicate indicator or something similar. 4852% 4853% Example: 4854% 4855% exc_desc(jpl_call_static,no_such_method(M), 4856% jpl_call/4, 4857% existence_error(method,M), 4858% 'some text') 4859% 4860% exc_desc(jpl_call_static,no_such_method(M), 4861% _, 4862% existence_error(method,M), 4863% 'some text') 4864% 4865% The "Msg" is a user-readable message. For now, it is not dynamically 4866% constructed (i.e. using format/3 calls) inside of exc_desc/5, nor is 4867% internationalization supported for that matter. In some cases, the "Msg" 4868% has been created by caller and is passed in inside "LookupTerm", from where 4869% it is unification-picked-out-of-there into arg 5. 4870% 4871% The "Formal" is exactly the "formal term" that will used in the "exception 4872% term", and it is built by unification doing pick/put against "LookupTerm". 4873% It may or may not be ISO-Standard. 4874% 4875% Note that the fact that we adhere to ISO standard atoms instead of defining 4876% our own for JPL has the advantage that exception-printing handlers on the 4877% toplevel still work but the generated text is confusing: for example the 4878% exception-generating handler receives a "type_error" (which is meant to 4879% indicate a type problem inside a Prolog program, but here is also used to 4880% indicate a type problem of a very different nature, e.g. the caller wants 4881% to instantiate a Java interface) and the argument passed in the formal is 4882% the name of the Java class as an atom. Then the printing handler will say 4883% this: "there is a problem because this is an atom: 'foo.bar.Interface'" and 4884% only by reading the cleartext message will the actual problem be revealed: 4885% "you tried to instantiate an interface". 4886% --- 4887 4888safe_type_to_classname(Type,CN) :- 4889 catch( 4890 (jpl_type_to_classname(Type,CN) 4891 -> true 4892 ; with_output_to(atom(CN),format("~q",[Type]))), 4893 _DontCareCatcher, 4894 CN='???'). 4895 4896exc_desc(jpl_new,x_is_var, 4897 jpl_new/3, 4898 instantiation_error, 4899 '1st arg must be bound to a classname, descriptor or object type'). 4900 4901exc_desc(jpl_new,x_not_classname(X), 4902 jpl_new/3, 4903 domain_error(classname,X), 4904 'if 1st arg is an atom, it must be a classname or descriptor'). 4905 4906exc_desc(jpl_new,x_not_instantiable(X), 4907 jpl_new/3, 4908 type_error(instantiable,X), 4909 '1st arg must be a classname, descriptor or object type'). 4910 4911exc_desc(jpl_new,not_a_jpl_term(X), 4912 jpl_new/3, 4913 type_error(term,X), 4914 'result is not a org.jpl7.Term instance as required'). 4915 4916% --- 4917 4918exc_desc(jpl_new_class,params_is_var, 4919 jpl_new/3, 4920 instantiation_error, 4921 '2nd arg must be a proper list of valid parameters for a constructor'). 4922 4923exc_desc(jpl_new_class,params_is_not_list(Params), 4924 jpl_new/3, 4925 type_error(list,Params), 4926 '2nd arg must be a proper list of valid parameters for a constructor'). 4927 4928exc_desc(jpl_new_class,class_is_interface(Type), 4929 jpl_new/3, 4930 type_error(concrete_class,CN), 4931 'cannot create instance of an interface') :- safe_type_to_classname(Type,CN). 4932 4933exc_desc(jpl_new_class,class_without_constructor(Type,Arity), 4934 jpl_new/3, 4935 existence_error(constructor,CN/Arity), 4936 'no constructor found with the corresponding quantity of parameters') :- safe_type_to_classname(Type,CN). 4937 4938exc_desc(jpl_new_class,acyclic(X,Msg), 4939 jpl_new/3, 4940 type_error(acyclic,X), 4941 Msg). 4942 4943exc_desc(jpl_new_class,bad_jpl_datum(Params), 4944 jpl_new/3, 4945 domain_error(list(jpl_datum),Params), 4946 'one or more of the actual parameters is not a valid representation of any Java value or object'). 4947 4948exc_desc(jpl_new_class,single_constructor_mismatch(Co), 4949 jpl_new/3, 4950 existence_error(constructor,Co), 4951 'the actual parameters are not assignable to the formal parameter types of the only constructor which takes this qty of parameters'). 4952 4953exc_desc(jpl_new_class,any_constructor_mismatch(Params), 4954 jpl_new/3, 4955 type_error(constructor_args,Params), 4956 'the actual parameters are not assignable to the formal parameter types of any of the constructors which take this qty of parameters'). 4957 4958exc_desc(jpl_new_class,constructor_multimatch(Params), 4959 jpl_new/3, 4960 type_error(constructor_params,Params), 4961 'more than one most-specific matching constructor (shouldn''t happen)'). 4962 4963exc_desc(jpl_new_class,class_is_abstract(Type), 4964 jpl_new/3, 4965 type_error(concrete_class,CN), 4966 'cannot create instance of an abstract class') :- safe_type_to_classname(Type,CN). 4967 4968% --- 4969 4970exc_desc(jpl_new_array,params_is_var, 4971 jpl_new/3, 4972 instantiation_error, 4973 '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'). 4974 4975exc_desc(jpl_new_array,params_is_negative(Params), 4976 jpl_new/3, 4977 domain_error(array_length,Params), 4978 'when constructing a new array, if the 2nd arg is an integer (denoting the required array length) then it must be non-negative'). 4979 4980% --- 4981 4982exc_desc(jpl_new_primitive,primitive_type_requested(T), 4983 jpl_new/3, 4984 domain_error(object_type,T), 4985 'cannot construct an instance of a primitive type'). 4986 4987% the call to this is commented out in jpl.pl 4988exc_desc(jpl_new_primitive,params_is_var, 4989 jpl_new/3, 4990 instantiation_error, 4991 'when constructing a new instance of a primitive type, 2nd arg must be bound (to a representation of a suitable value)'). 4992 4993% the call to this is commented out in jpl.pl 4994exc_desc(jpl_new_primitive,params_is_bad(Params), 4995 jpl_new/3, 4996 domain_error(constructor_args,Params),Msg) :- 4997 atomic_list_concat([ 4998 'when constructing a new instance of a primitive type, 2nd arg must either be an ', 4999 'empty list (indicating that the default value of that type is required) or a ', 5000 'list containing exactly one representation of a suitable value'],Msg). 5001 5002% --- 5003 5004exc_desc(jpl_new_catchall,catchall(T), 5005 jpl_new/3, 5006 domain_error(jpl_type,T), 5007 '1st arg must denote a known or plausible type'). 5008 5009% --- 5010 5011exc_desc(jpl_call,arg1_is_var, 5012 jpl_call/4, 5013 instantiation_error, 5014 '1st arg must be bound to an object, classname, descriptor or type'). 5015 5016exc_desc(jpl_call,no_such_class(X), 5017 jpl_call/4, 5018 existence_error(class,X), 5019 'the named class cannot be found'). 5020 5021exc_desc(jpl_call,arg1_is_bad(X), 5022 jpl_call/4, 5023 type_error(class_name_or_descriptor,X), 5024 '1st arg must be an object, classname, descriptor or type'). 5025 5026exc_desc(jpl_call,arg1_is_array(X), 5027 jpl_call/4, 5028 type_error(object_or_class,X), 5029 'cannot call a static method of an array type, as none exists'). 5030 5031exc_desc(jpl_call,arg1_is_bad_2(X), 5032 jpl_call/4, 5033 domain_error(object_or_class,X), 5034 '1st arg must be an object, classname, descriptor or type'). 5035 5036exc_desc(jpl_call,mspec_is_var, 5037 jpl_call/4, 5038 instantiation_error, 5039 '2nd arg must be an atom naming a public method of the class or object'). 5040 5041exc_desc(jpl_call,mspec_is_bad(Mspec), 5042 jpl_call/4, 5043 type_error(method_name,Mspec), 5044 '2nd arg must be an atom naming a public method of the class or object'). 5045 5046exc_desc(jpl_call,acyclic(Te,Msg), 5047 jpl_call/4, 5048 type_error(acyclic,Te), 5049 Msg). 5050 5051exc_desc(jpl_call,nonconvertible_params(Params), 5052 jpl_call/4, 5053 type_error(method_params,Params), 5054 'not all actual parameters are convertible to Java values or references'). 5055 5056exc_desc(jpl_call,arg3_is_var, 5057 jpl_call/4, 5058 instantiation_error, 5059 '3rd arg must be a proper list of actual parameters for the named method'). 5060 5061exc_desc(jpl_call,arg3_is_bad(Params), 5062 jpl_call/4, 5063 type_error(method_params,Params), 5064 '3rd arg must be a proper list of actual parameters for the named method'). 5065 5066exc_desc(jpl_call,not_a_jpl_term(X), 5067 jpl_call/4, 5068 type_error(jni_jref,X), 5069 'result is not a org.jpl7.Term instance as required'). 5070 5071% --- 5072 5073exc_desc(jpl_call_instance,no_such_method(M), 5074 jpl_call/4, 5075 existence_error(method,M), 5076 'the class or object has no public methods with the given name and quantity of parameters'). 5077 5078exc_desc(jpl_call_instance,param_not_assignable(P), 5079 jpl_call/4, 5080 type_error(method_params,P), 5081 'the actual parameters are not assignable to the formal parameters of any of the named methods'). 5082 5083exc_desc(jpl_call_instance,multiple_most_specific(M), 5084 jpl_call/4, 5085 existence_error(most_specific_method,M), 5086 'more than one most-specific method is found for the actual parameters (this should not happen)'). 5087 5088% --- 5089 5090exc_desc(jpl_call_static,no_such_method(M), 5091 jpl_call/4, 5092 existence_error(method,M), 5093 'the class has no public static methods with the given name and quantity of parameters'). 5094 5095exc_desc(jpl_call_static,param_not_assignable(P), 5096 jpl_call/4, 5097 type_error(method_params,P), 5098 'the actual parameters are not assignable to the formal parameters of any of the named methods'). 5099 5100exc_desc(jpl_call_static,multiple_most_specific(M), 5101 jpl_call/4, 5102 existence_error(most_specific_method,M), 5103 'more than one most-specific method is found for the actual parameters (this should not happen)'). 5104 5105% --- 5106 5107exc_desc(jpl_get,arg1_is_var, 5108 jpl_get/3, 5109 instantiation_error, 5110 '1st arg must be bound to an object, classname, descriptor or type'). 5111 5112exc_desc(jpl_get,named_class_not_found(Type), 5113 jpl_get/3, 5114 existence_error(class,CN), 5115 'the named class cannot be found') :- safe_type_to_classname(Type,CN). 5116 5117exc_desc(jpl_get,arg1_is_bad(X), 5118 jpl_get/3, 5119 type_error(class_name_or_descriptor,X), 5120 '1st arg must be an object, classname, descriptor or type'). 5121 5122exc_desc(jpl_get,arg1_is_bad_2(X), 5123 jpl_get/3, 5124 domain_error(object_or_class,X), 5125 '1st arg must be an object, classname, descriptor or type'). 5126 5127exc_desc(jpl_get,not_a_jpl_term(X), 5128 jpl_get/3, 5129 type_error(jni_ref,X), 5130 'result is not a org.jpl7.Term instance as required'). 5131 5132% --- 5133 5134exc_desc(jpl_get_static,arg2_is_var, 5135 jpl_get/3, 5136 instantiation_error, 5137 '2nd arg must be bound to an atom naming a public field of the class'). 5138 5139exc_desc(jpl_get_static,arg2_is_bad(F), 5140 jpl_get/3, 5141 type_error(field_name,F), 5142 '2nd arg must be an atom naming a public field of the class'). 5143 5144exc_desc(jpl_get_static,no_such_field(F), 5145 jpl_get/3, 5146 existence_error(field,F), 5147 'the class or object has no public static field with the given name'). 5148 5149exc_desc(jpl_get_static,multiple_fields(F), 5150 jpl_get/3, 5151 existence_error(unique_field,F), 5152 'more than one field is found with the given name'). 5153 5154% --- 5155 5156exc_desc(jpl_get_instance,arg2_is_var, 5157 jpl_get/3, 5158 instantiation_error, 5159 '2nd arg must be bound to an atom naming a public field of the class or object'). 5160 5161exc_desc(jpl_get_instance,arg2_is_bad(X), 5162 jpl_get/3, 5163 type_error(field_name,X), 5164 '2nd arg must be an atom naming a public field of the class or object'). 5165 5166exc_desc(jpl_get_instance,no_such_field(Fname), 5167 jpl_get/3, 5168 existence_error(field,Fname), 5169 'the class or object has no public field with the given name'). 5170 5171exc_desc(jpl_get_instance,multiple_fields(Fname), 5172 jpl_get/3, 5173 existence_error(unique_field,Fname), 5174 'more than one field is found with the given name'). 5175 5176% --- 5177 5178exc_desc(jpl_get_instance_array,arg2_is_var, 5179 jpl_get/3, 5180 instantiation_error, 5181 'when 1st arg is an array, 2nd arg must be bound to an index, an index range, or ''length'''). 5182 5183exc_desc(jpl_get_instance_array,arg2_is_bad(X), 5184 jpl_get/3, 5185 domain_error(array_index,X), 5186 'when 1st arg is an array, integral 2nd arg must be non-negative'). 5187 5188exc_desc(jpl_get_instance_array,arg2_is_too_large(X), 5189 jpl_get/3, 5190 domain_error(array_index,X), 5191 'when 1st arg is an array, integral 2nd arg must not exceed upper bound of array'). 5192 5193exc_desc(jpl_get_instance_array,bad_range_low(R), 5194 jpl_get/3, 5195 domain_error(array_index_range,R), 5196 'lower bound of array index range must not exceed upper bound of array'). 5197 5198exc_desc(jpl_get_instance_array,bad_range_high(R), 5199 jpl_get/3, 5200 domain_error(array_index_range,R), 5201 'upper bound of array index range must not exceed upper bound of array'). 5202 5203exc_desc(jpl_get_instance_array,bad_range_pair_values(R), 5204 jpl_get/3, 5205 domain_error(array_index_range,R), 5206 'array index range must be a non-decreasing pair of non-negative integers'). 5207 5208exc_desc(jpl_get_instance_array,bad_range_pair_types(R), 5209 jpl_get/3, 5210 type_error(array_index_range,R), 5211 'array index range must be a non-decreasing pair of non-negative integers'). 5212 5213exc_desc(jpl_get_instance_array,no_such_field(F), 5214 jpl_get/3, 5215 domain_error(array_field_name,F), 5216 'the array has no public field with the given name'). 5217 5218exc_desc(jpl_get_instance_array,wrong_spec(F), 5219 jpl_get/3, 5220 type_error(array_lookup_spec,F), 5221 'when 1st arg is an array, 2nd arg must be an index, an index range, or ''length'''). 5222 5223% --- 5224 5225exc_desc(jpl_set,arg1_is_var, 5226 jpl_set/3, 5227 instantiation_error, 5228 '1st arg must be an object, classname, descriptor or type'). 5229 5230exc_desc(jpl_set,classname_does_not_resolve(X), 5231 jpl_set/3, 5232 existence_error(class,X), 5233 'the named class cannot be found'). 5234 5235exc_desc(jpl_set,named_class_not_found(Type), 5236 jpl_set/3, 5237 existence_error(class,CN), 5238 'the named class cannot be found') :- safe_type_to_classname(Type,CN). 5239 5240exc_desc(jpl_set,acyclic(X,Msg), 5241 jpl_set/3, 5242 type_error(acyclic,X), 5243 Msg). 5244 5245exc_desc(jpl_set,arg1_is_bad(X), 5246 jpl_set/3, 5247 domain_error(object_or_class,X), 5248 '1st arg must be an object, classname, descriptor or type'). 5249 5250% --- 5251 5252exc_desc(jpl_set_instance_class,arg2_is_var, 5253 jpl_set/3, 5254 instantiation_error, 5255 '2nd arg must be bound to the name of a public, non-final field'). 5256 5257exc_desc(jpl_set_instance_class,arg2_is_bad(Fname), 5258 jpl_set/3, 5259 type_error(field_name,Fname), 5260 '2nd arg must be the name of a public, non-final field'). 5261 5262exc_desc(jpl_set_instance_class,no_such_field(Fname), 5263 jpl_set/3, 5264 existence_error(field,Fname), 5265 'no public fields of the object have this name'). 5266 5267exc_desc(jpl_set_instance_class,field_is_final(Fname), 5268 jpl_set/3, 5269 permission_error(modify,final_field,Fname), 5270 'cannot assign a value to a final field (actually you could but I''ve decided not to let you)'). 5271 5272exc_desc(jpl_set_instance_class,incompatible_value(Type,V), 5273 jpl_set/3, 5274 type_error(CN,V), 5275 'the value is not assignable to the named field of the class') :- safe_type_to_classname(Type,CN). 5276 5277exc_desc(jpl_set_instance_class,arg3_is_bad(V), 5278 jpl_set/3, 5279 type_error(field_value,V), 5280 '3rd arg does not represent any Java value or object'). 5281 5282exc_desc(jpl_set_instance_class,multiple_fields(Fname), 5283 jpl_set/3, 5284 existence_error(field,Fname), 5285 'more than one public field of the object has this name (this should not happen)'). 5286 5287% --- 5288 5289exc_desc(jpl_set_instance_array,arg3_is_var, 5290 jpl_set/3, 5291 instantiation_error, 5292 'when 1st arg is an array, 3rd arg must be bound to a suitable element value or list of values'). 5293 5294exc_desc(jpl_set_instance_array,arg2_is_var, 5295 jpl_set/3, 5296 instantiation_error, 5297 'when 1st arg is an array, 2nd arg must be bound to an index or index range'). 5298 5299exc_desc(jpl_set_instance_array,arg2_is_bad(FSpec), 5300 jpl_set/3, 5301 domain_error(array_index,FSpec), 5302 'when 1st arg is an array, an integral 2nd arg must be a non-negative index'). 5303 5304exc_desc(jpl_set_instance_array,no_values(Fspec,Vs), 5305 jpl_set/3, 5306 domain_error(array_element(Fspec),Vs), 5307 'no values for array element assignment: needs one'). 5308 5309exc_desc(jpl_set_instance_array,more_than_one_value(Fspec,Vs), 5310 jpl_set/3, 5311 domain_error(array_element(Fspec),Vs), 5312 'too many values for array element assignment: needs one'). 5313 5314exc_desc(jpl_set_instance_array,too_few_values(N-M,Vs), 5315 jpl_set/3, 5316 domain_error(array_elements(N-M),Vs), 5317 'too few values for array range assignment'). 5318 5319exc_desc(jpl_set_instance_array,too_many_values(N-M,Vs), 5320 jpl_set/3, 5321 domain_error(array_elements(N-M),Vs), 5322 'too many values for array range assignment'). 5323 5324exc_desc(jpl_set_instance_array,bad_range_pair_values(N-M), 5325 jpl_set/3, 5326 domain_error(array_index_range,N-M), 5327 'array index range must be a non-decreasing pair of non-negative integers'). 5328 5329exc_desc(jpl_set_instance_array,bad_range_pair_types(N-M), 5330 jpl_set/3, 5331 type_error(array_index_range,N-M), 5332 'array index range must be a non-decreasing pair of non-negative integers'). 5333 5334exc_desc(jpl_set_instance_array,cannot_assign_to_final_field, 5335 jpl_set/3, 5336 permission_error(modify,final_field,length), 5337 'cannot assign a value to a final field'). 5338 5339exc_desc(jpl_set_instance_array,no_such_field(Fspec), 5340 jpl_set/3, 5341 existence_error(field,Fspec), 5342 'array has no field with that name'). 5343 5344exc_desc(jpl_set_instance_array,arg2_is_bad_2(Fspec), 5345 jpl_set/3, 5346 domain_error(array_index,Fspec), 5347 'when 1st arg is an array object, 2nd arg must be a non-negative index or index range'). 5348 5349% --- 5350 5351exc_desc(jpl_set_static,arg2_is_unbound, 5352 jpl_set/3, 5353 instantiation_error, 5354 'when 1st arg denotes a class, 2nd arg must be bound to the name of a public, static, non-final field'). 5355 5356exc_desc(jpl_set_static,arg2_is_bad(Fname), 5357 jpl_set/3, 5358 type_error(field_name,Fname), 5359 'when 1st arg denotes a class, 2nd arg must be the name of a public, static, non-final field'). 5360 5361exc_desc(jpl_set_static,no_such_public_static_field(field,Fname), 5362 jpl_set/3, 5363 existence_error(field,Fname), 5364 'class has no public static fields of this name'). 5365 5366exc_desc(jpl_set_static,cannot_assign_final_field(Fname), 5367 jpl_set/3, 5368 permission_error(modify,final_field,Fname), 5369 'cannot assign a value to a final field'). 5370 5371exc_desc(jpl_set_static,value_not_assignable(Type,V), 5372 jpl_set/3, 5373 type_error(CN,V), 5374 'the value is not assignable to the named field of the class') :- safe_type_to_classname(Type,CN). 5375 5376exc_desc(jpl_set_static,arg3_is_bad(field_value,V), 5377 jpl_set/3, 5378 type_error(field_value,V), 5379 '3rd arg does not represent any Java value or object'). 5380 5381exc_desc(jpl_set_static,multiple_matches(field,Fname), 5382 jpl_set/3, 5383 existence_error(field,Fname), 5384 'more than one public static field of the class has this name (this should not happen)(?)'). 5385 5386% --- 5387 5388exc_desc(jpl_set_array,not_all_values_assignable(T,Ds), 5389 jpl_set/3, 5390 type_error(array(T),Ds), 5391 'not all values are assignable to the array element type'). 5392 5393exc_desc(jpl_set_array,not_all_values_convertible(T,Ds), 5394 jpl_set/3, 5395 type_error(array(T),Ds), 5396 'not all values are convertible to Java values or references'). 5397 5398exc_desc(jpl_set_array,element_type_unknown(array_element_type,T), 5399 jpl_set/3, 5400 type_error(array_element_type,T), 5401 'array element type is unknown: neither a class, nor an array type, nor a primitive type'). 5402 5403% --- 5404 5405exc_desc(jpl_datum_to_type,is_cyclic(Term), 5406 jpl_call/4, % I don't know why, but the tests expect jpl_call/4 here 5407 type_error(acyclic,Term), 5408 'must be acyclic'). 5409 5410% --- 5411 5412exc_desc(jpl_type_to_class,arg1_is_var, 5413 jpl_type_to_class/2, 5414 instantiation_error, 5415 '1st arg must be bound to a JPL type'). 5416 5417% --- 5418 5419exc_desc(check_lib,lib_not_found(Name,Msg), 5420 check_lib/2, 5421 existence_error(library,Name), 5422 Msg). 5423 5424 5425 /******************************* 5426 * Initialize JVM * 5427 *******************************/ 5428 5429:- 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.