| author | wenzelm | 
| Sat, 08 Jul 2023 19:28:26 +0200 | |
| changeset 78271 | c0dc000d2a40 | 
| parent 75409 | 5640c4db7d37 | 
| child 83033 | 1ac7cc481c4f | 
| permissions | -rw-r--r-- | 
| 56905 | 1 | /* Title: Pure/General/untyped.scala | 
| 2 | Author: Makarius | |
| 3 | ||
| 4 | Untyped, unscoped, unchecked access to JVM objects. | |
| 5 | */ | |
| 6 | ||
| 7 | package isabelle | |
| 8 | ||
| 9 | ||
| 72973 | 10 | import java.lang.reflect.{Constructor, Method, Field}
 | 
| 59080 
611914621edb
added Untyped.method convenience (for *this* class only);
 wenzelm parents: 
59079diff
changeset | 11 | |
| 
611914621edb
added Untyped.method convenience (for *this* class only);
 wenzelm parents: 
59079diff
changeset | 12 | |
| 75393 | 13 | object Untyped {
 | 
| 14 |   def constructor[C](c: Class[C], arg_types: Class[_]*): Constructor[C] = {
 | |
| 72973 | 15 | val con = c.getDeclaredConstructor(arg_types: _*) | 
| 16 | con.setAccessible(true) | |
| 17 | con | |
| 18 | } | |
| 19 | ||
| 75409 | 20 |   def the_constructor[C](c:  Class[C]): Constructor[C] = {
 | 
| 21 |     c.getDeclaredConstructors().toList match {
 | |
| 22 | case List(con) => | |
| 23 | con.setAccessible(true) | |
| 24 | con.asInstanceOf[Constructor[C]] | |
| 25 |       case Nil => error("No constructor for " + c)
 | |
| 26 |       case _ => error("Multiple constructors for " + c)
 | |
| 27 | } | |
| 28 | } | |
| 29 | ||
| 75393 | 30 |   def method(c: Class[_], name: String, arg_types: Class[_]*): Method = {
 | 
| 59080 
611914621edb
added Untyped.method convenience (for *this* class only);
 wenzelm parents: 
59079diff
changeset | 31 | val m = c.getDeclaredMethod(name, arg_types: _*) | 
| 
611914621edb
added Untyped.method convenience (for *this* class only);
 wenzelm parents: 
59079diff
changeset | 32 | m.setAccessible(true) | 
| 
611914621edb
added Untyped.method convenience (for *this* class only);
 wenzelm parents: 
59079diff
changeset | 33 | m | 
| 
611914621edb
added Untyped.method convenience (for *this* class only);
 wenzelm parents: 
59079diff
changeset | 34 | } | 
| 
611914621edb
added Untyped.method convenience (for *this* class only);
 wenzelm parents: 
59079diff
changeset | 35 | |
| 75408 | 36 |   def the_method(c: Class[_], name: String): Method = {
 | 
| 37 |     c.getDeclaredMethods().iterator.filter(m => m.getName == name).toList match {
 | |
| 38 | case List(m) => | |
| 39 | m.setAccessible(true) | |
| 40 | m | |
| 75409 | 41 |       case Nil => error("No method " + quote(name) + " for " + c)
 | 
| 75408 | 42 |       case _ => error("Multiple methods " + quote(name) + " for " + c)
 | 
| 43 | } | |
| 44 | } | |
| 45 | ||
| 46 |   def classes(c0: Class[_ <: AnyRef]): Iterator[Class[_ <: AnyRef]] = new Iterator[Class[_ <: AnyRef]] {
 | |
| 47 | private var next_elem: Class[_ <: AnyRef] = c0 | |
| 73337 | 48 | def hasNext: Boolean = next_elem != null | 
| 58682 | 49 |     def next(): Class[_ <: AnyRef] = {
 | 
| 50 | val c = next_elem | |
| 51 | next_elem = c.getSuperclass.asInstanceOf[Class[_ <: AnyRef]] | |
| 52 | c | |
| 56905 | 53 | } | 
| 54 | } | |
| 58682 | 55 | |
| 75408 | 56 |   def class_field(c0: Class[_ <: AnyRef], x: String): Field = {
 | 
| 63419 | 57 | val iterator = | 
| 58 |       for {
 | |
| 75408 | 59 | c <- classes(c0) | 
| 63419 | 60 | field <- c.getDeclaredFields.iterator | 
| 61 | if field.getName == x | |
| 62 |       } yield {
 | |
| 63 | field.setAccessible(true) | |
| 64 | field | |
| 65 | } | |
| 73344 | 66 | if (iterator.hasNext) iterator.next() | 
| 75408 | 67 |     else error("No field " + quote(x) + " for " + c0)
 | 
| 63419 | 68 | } | 
| 69 | ||
| 75409 | 70 | def get_static[A](c: Class[_ <: AnyRef], x: String): A = | 
| 71 | class_field(c, x).get(null).asInstanceOf[A] | |
| 72 | ||
| 75408 | 73 | def field(obj: AnyRef, x: String): Field = class_field(obj.getClass, x) | 
| 74 | ||
| 59079 | 75 | def get[A](obj: AnyRef, x: String): A = | 
| 76 | if (obj == null) null.asInstanceOf[A] | |
| 63419 | 77 | else field(obj, x).get(obj).asInstanceOf[A] | 
| 78 | ||
| 79 | def set[A](obj: AnyRef, x: String, y: A): Unit = | |
| 80 | field(obj, x).set(obj, y) | |
| 56905 | 81 | } |