Showing the changes to java/pkg/java/lang/reflect/reflect.b (1 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,327 @@ | |||
| 1 | implement Reflect; | ||
| 2 | |||
| 3 | include "jni.m"; | ||
| 4 | jni : JNI; | ||
| 5 | cast : Cast; | ||
| 6 | |||
| 7 | JObject, | ||
| 8 | JClass, | ||
| 9 | JArrayJClass, | ||
| 10 | JArrayJObject, | ||
| 11 | Value : import jni; | ||
| 12 | OK, | ||
| 13 | ERR, | ||
| 14 | TRUE, | ||
| 15 | FALSE, | ||
| 16 | #T_OBJECT, T_ARRAY, | ||
| 17 | T_BOOLEAN, | ||
| 18 | T_BYTE, | ||
| 19 | T_CHAR, | ||
| 20 | T_SHORT, | ||
| 21 | T_INT, | ||
| 22 | T_LONG, | ||
| 23 | T_FLOAT, | ||
| 24 | T_DOUBLE : import JNI; | ||
| 25 | |||
| 26 | ClassData : import JNI; | ||
| 27 | |||
| 28 | include "reflect.m"; | ||
| 29 | |||
| 30 | wrapper_class := array[T_LONG-T_BOOLEAN+1] of ClassData; | ||
| 31 | wrapper_name := array[] of { "Boolean", | ||
| 32 | "Character", | ||
| 33 | "Float", | ||
| 34 | "Double", | ||
| 35 | "Byte", | ||
| 36 | "Short", | ||
| 37 | "Integer", | ||
| 38 | "Long" }; | ||
| 39 | type_string := "ZCFDBSIJ"; | ||
| 40 | |||
| 41 | illegalarg := "java.lang.IllegalArgumentException"; | ||
| 42 | nullptr := "java.lang.NullPointerException"; | ||
| 43 | |||
| 44 | init(jni_m : JNI) { | ||
| 45 | jni = jni_m; | ||
| 46 | for ( i := 0; i <= T_LONG - T_BOOLEAN; i++ ) | ||
| 47 | wrapper_class[i] = jni->FindClass("java/lang/" + wrapper_name[i]); | ||
| 48 | cast = jni->CastMod(); | ||
| 49 | } | ||
| 50 | |||
| 51 | widen(have, want : int, val : ref Value) : ref Value | ||
| 52 | { | ||
| 53 | if ( have == want ) | ||
| 54 | return val; | ||
| 55 | havetype := have; | ||
| 56 | wanttype := want; | ||
| 57 | valint : int; | ||
| 58 | valbig : big; | ||
| 59 | valreal : real; | ||
| 60 | if ( havetype == 0 || wanttype == 0 ) | ||
| 61 | return nil; | ||
| 62 | pick sw := val { | ||
| 63 | TByte => | ||
| 64 | valint = int sw.jbyte; | ||
| 65 | valbig = big valint; | ||
| 66 | valreal = real valint; | ||
| 67 | TShort => | ||
| 68 | valint = sw.jshort; | ||
| 69 | valbig = big valint; | ||
| 70 | valreal = real valint; | ||
| 71 | TChar => | ||
| 72 | valint = sw.jchar; | ||
| 73 | valbig = big valint; | ||
| 74 | valreal = real valint; | ||
| 75 | TInt => | ||
| 76 | valint = sw.jint; | ||
| 77 | valbig = big valint; | ||
| 78 | valreal = real valint; | ||
| 79 | TLong => | ||
| 80 | valbig = sw.jlong; | ||
| 81 | valreal = real valbig; | ||
| 82 | TFloat => | ||
| 83 | valreal = sw.jfloat; | ||
| 84 | } | ||
| 85 | case ( wanttype ) { | ||
| 86 | T_BOOLEAN or T_BYTE or T_CHAR => | ||
| 87 | return nil; | ||
| 88 | T_SHORT => | ||
| 89 | case ( havetype ) { | ||
| 90 | T_BYTE => | ||
| 91 | sw := ref Value.TShort; | ||
| 92 | sw.jshort = valint; | ||
| 93 | val = sw; | ||
| 94 | * => | ||
| 95 | return nil; | ||
| 96 | } | ||
| 97 | T_INT => | ||
| 98 | case ( havetype ) { | ||
| 99 | T_BYTE or T_SHORT or T_CHAR => | ||
| 100 | sw := ref Value.TInt; | ||
| 101 | sw.jint = valint; | ||
| 102 | val = sw; | ||
| 103 | * => | ||
| 104 | return nil; | ||
| 105 | } | ||
| 106 | T_LONG => | ||
| 107 | case ( havetype ) { | ||
| 108 | T_BYTE or T_SHORT or T_CHAR or T_INT => | ||
| 109 | sw := ref Value.TLong; | ||
| 110 | sw.jlong = valbig; | ||
| 111 | val = sw; | ||
| 112 | * => | ||
| 113 | return nil; | ||
| 114 | } | ||
| 115 | T_FLOAT => | ||
| 116 | case ( havetype ) { | ||
| 117 | T_BYTE or T_SHORT or T_CHAR or T_INT or T_LONG => | ||
| 118 | sw := ref Value.TFloat; | ||
| 119 | sw.jfloat = valreal; | ||
| 120 | val = sw; | ||
| 121 | * => | ||
| 122 | return nil; | ||
| 123 | } | ||
| 124 | T_DOUBLE => | ||
| 125 | case ( havetype ) { | ||
| 126 | T_BYTE or T_SHORT or T_CHAR or T_INT or T_LONG or T_FLOAT => | ||
| 127 | sw := ref Value.TDouble; | ||
| 128 | sw.jdouble = valreal; | ||
| 129 | val = sw; | ||
| 130 | * => | ||
| 131 | return nil; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | return val; | ||
| 135 | } | ||
| 136 | BuildArgList(parms : JArrayJClass, arg : JArrayJObject) : array of ref Value | ||
| 137 | { | ||
| 138 | # | ||
| 139 | # First do some checking. | ||
| 140 | # | ||
| 141 | l := 0; | ||
| 142 | formal: array of JClass; | ||
| 143 | actual: array of JObject; | ||
| 144 | args: array of ref Value; | ||
| 145 | if ( parms != nil ) { | ||
| 146 | if ( arg == nil ) | ||
| 147 | jni->ThrowException(nullptr, "constructor requires parameters"); | ||
| 148 | if ( len parms.ary != len arg.ary ) | ||
| 149 | jni->ThrowException(illegalarg, "Wrong number of args"); | ||
| 150 | l = len parms.ary; | ||
| 151 | formal = parms.ary; # array of JClass | ||
| 152 | actual = arg.ary; # array of JObject | ||
| 153 | args = array[l] of ref Value; | ||
| 154 | } | ||
| 155 | else # There are no formal parameters | ||
| 156 | if ( arg != nil && len arg.ary != 0 ) # But there are actual arguments | ||
| 157 | jni->ThrowException(illegalarg, "Wrong number of args"); | ||
| 158 | |||
| 159 | # | ||
| 160 | # March through the arguments, checking for type as we go. | ||
| 161 | # | ||
| 162 | for ( i := 0; i < l; i++ ) { | ||
| 163 | # | ||
| 164 | # Is the formal parameter a primitive? | ||
| 165 | # | ||
| 166 | if ( (want := jni->PrimitiveIndex(formal[i], 1)) > 0 ) { | ||
| 167 | # | ||
| 168 | # Actual parameter should be (derived from) a wrapper, and | ||
| 169 | # be able to be widened to the formal parameter type. | ||
| 170 | # | ||
| 171 | (typ, parmval) := GetVal(actual[i]); | ||
| 172 | if ( (val := widen(want, typ, parmval)) != nil ) | ||
| 173 | args[i] = val; | ||
| 174 | else | ||
| 175 | jni->ThrowException(illegalarg, "Argument " + string (i+1) + | ||
| 176 | ", can't cast"); | ||
| 177 | } | ||
| 178 | else if ( jni->IsInstanceOf(actual[i], formal[i].class) == JNI->TRUE ) { | ||
| 179 | val := ref Value.TObject; | ||
| 180 | val.jobj = actual[i]; | ||
| 181 | args[i] = val; | ||
| 182 | } | ||
| 183 | else | ||
| 184 | jni->ThrowException(illegalarg, "Argument " + string (i+1) + | ||
| 185 | " wrong type"); | ||
| 186 | } | ||
| 187 | return args; | ||
| 188 | } | ||
| 189 | # | ||
| 190 | # Return a JClass corresponding to the Java type t. | ||
| 191 | # | ||
| 192 | Class(t : int) : JClass | ||
| 193 | { | ||
| 194 | if ( t < T_BOOLEAN || t > T_LONG ) | ||
| 195 | return nil; | ||
| 196 | return jni->GetClassObject(wrapper_class[t - T_BOOLEAN]); | ||
| 197 | } | ||
| 198 | # | ||
| 199 | # Return a Class Object corresponding to the Java type t. | ||
| 200 | # | ||
| 201 | ClassObject(t : int) : JObject | ||
| 202 | { | ||
| 203 | return cast->FromJClass(Class(t)); | ||
| 204 | } | ||
| 205 | # | ||
| 206 | # Given the java type, get the Class object representing this | ||
| 207 | # type, and return as a Value. | ||
| 208 | # | ||
| 209 | GetPrimitiveClass(typ : int) : ref Value | ||
| 210 | { | ||
| 211 | return jni->GetStaticField(wrapper_class[typ - T_BOOLEAN], "TYPE", | ||
| 212 | "Ljava/lang/Class;"); | ||
| 213 | } | ||
| 214 | # | ||
| 215 | # If the Object o is a wrapper for a Java primitive type, return the | ||
| 216 | # primitive value (in a Value adt) and the type index. | ||
| 217 | # Otherwise, return 0 and a nil Value. | ||
| 218 | # | ||
| 219 | GetVal(o : JObject) : (int, ref Value) | ||
| 220 | { | ||
| 221 | j := T_BOOLEAN; | ||
| 222 | for ( i := j; i <= T_LONG; i++ ) { | ||
| 223 | if ( jni->IsInstanceOf(o, wrapper_class[i-j]) == TRUE ) { | ||
| 224 | val := jni->GetObjField(o, "value", type_string[i-j:i-j+1]); | ||
| 225 | return (i, val); | ||
| 226 | } | ||
| 227 | } | ||
| 228 | return (0, nil); | ||
| 229 | } | ||
| 230 | # | ||
| 231 | # Convert a signature to a java type index. | ||
| 232 | # | ||
| 233 | SigToType(sig : string) : int | ||
| 234 | { | ||
| 235 | index : int; | ||
| 236 | case sig[0] { | ||
| 237 | 'Z' => | ||
| 238 | index = T_BOOLEAN; | ||
| 239 | 'B' => | ||
| 240 | index = T_BYTE; | ||
| 241 | 'C' => | ||
| 242 | index = T_CHAR; | ||
| 243 | 'S' => | ||
| 244 | index = T_SHORT; | ||
| 245 | 'I' => | ||
| 246 | index = T_INT; | ||
| 247 | 'J' => | ||
| 248 | index = T_LONG; | ||
| 249 | 'F' => | ||
| 250 | index = T_FLOAT; | ||
| 251 | 'D' => | ||
| 252 | index = T_DOUBLE; | ||
| 253 | * => | ||
| 254 | index = 0; | ||
| 255 | } | ||
| 256 | return index; | ||
| 257 | } | ||
| 258 | # | ||
| 259 | # Convert a java type index to a signature. | ||
| 260 | # | ||
| 261 | TypeToSig(typ : int) : string | ||
| 262 | { | ||
| 263 | if ( typ < T_BOOLEAN || typ > T_LONG ) | ||
| 264 | return nil; | ||
| 265 | return type_string[typ-T_BOOLEAN:typ-T_BOOLEAN+1]; | ||
| 266 | } | ||
| 267 | # | ||
| 268 | # Convert a Java type character to its corresponding type name. | ||
| 269 | # | ||
| 270 | TypeCharToName(c : int) : string | ||
| 271 | { | ||
| 272 | tname : string; | ||
| 273 | case c { | ||
| 274 | 'Z' => | ||
| 275 | tname = "boolean"; | ||
| 276 | 'B' => | ||
| 277 | tname = "byte"; | ||
| 278 | 'C' => | ||
| 279 | tname = "char"; | ||
| 280 | 'S' => | ||
| 281 | tname = "short"; | ||
| 282 | 'I' => | ||
| 283 | tname = "int"; | ||
| 284 | 'J' => | ||
| 285 | tname = "long"; | ||
| 286 | 'F' => | ||
| 287 | tname = "float"; | ||
| 288 | 'D' => | ||
| 289 | tname = "double"; | ||
| 290 | * => | ||
| 291 | tname = "blah"; | ||
| 292 | } | ||
| 293 | return tname; | ||
| 294 | } | ||
| 295 | # | ||
| 296 | # Calculate the type index of the quantity in val. If it isn't a | ||
| 297 | # Java primitive type, return 0; | ||
| 298 | # | ||
| 299 | ValType(val : ref Value) : int | ||
| 300 | { | ||
| 301 | pick sw := val { | ||
| 302 | TBoolean => return T_BOOLEAN; | ||
| 303 | TByte => return T_BYTE; | ||
| 304 | TChar => return T_CHAR; | ||
| 305 | TShort => return T_SHORT; | ||
| 306 | TInt => return T_INT; | ||
| 307 | TLong => return T_LONG; | ||
| 308 | TFloat => return T_FLOAT; | ||
| 309 | TDouble => return T_DOUBLE; | ||
| 310 | * => return 0; | ||
| 311 | } | ||
| 312 | } | ||
| 313 | # | ||
| 314 | # Create a wrapper Object for the primitive Java value corresponding | ||
| 315 | # to the argument. | ||
| 316 | # | ||
| 317 | ValueToObject(val : ref Value) : JObject | ||
| 318 | { | ||
| 319 | typ := ValType(val); | ||
| 320 | j := T_BOOLEAN; | ||
| 321 | jobj := jni->AllocObject(wrapper_class[typ - j]); | ||
| 322 | sig := "(" + type_string[typ-j:typ-j+1] + ")V"; | ||
| 323 | (nil, ok) := jni->CallMethod(jobj, "<init>", sig, array[] of { val }); | ||
| 324 | if ( ok == OK ) | ||
| 325 | return jobj; | ||
| 326 | return nil; | ||
| 327 | } | ||