Reflection
Reflection (run-time type inspection and code invocation) is a rather difficult thing to implement in a platform-independent manner, because different platforms have different levels of support for this. In addition, dynamically typed languages such as PHP and Python do not maintain reflection information such as the return type of a method, or type of a field.
The solution we have implemented to realize reflection for all platforms is the generation of reflection classes for all defined types.
To clarify, let's look at an example.
class myns::A {
void sayHello(String to) {
println("Hello, " + to);
}
}
If we generate code, typically 3 files will be generated. In the case of the Java back-end:
myns/A.java
myns/reflect/AClassInfo.java
myns/reflect/TypeOfA.java
The first is the actual class itself, if you look at it you will notice it has two methods, rather than one. There is the sayHello method, but also a getClassInfo() method.
This method will return an instance of the myns.reflect.AClassInfo class. This ClassInfo object has reflexive properties such as getSuperClass(), getFields() and getMethods(). Using these reflection methods, the structure of the class can be inspected, all the original type information (such as the types of parameters of methods) is preserved, even if the code is run on a dynamically typed platform such as Python or PHP.
Reflection, of course, is not only available at the level platform code, but also from PIL code itself. By using the .class property on objects and typeof on classes (e.g. typeof A), access can be gained to the reflection class objects.
The following code snippet, taken from the reflection unit tests demonstrates its use:
class AClass {
}
class BClass extends AClass {
void voidMethod() {
}
Int intMethod(Int intArg) {
}
}
class CClass {
Int a = 0;
String b = "";
}
void testInstanceOf() {
println("Instanceof tests");
var a = new AClass();
assert(a instanceof AClass, "instanceof AClass test");
assert(a instanceof Object, "instanceof Object test");
Object o = a;
assertEqual(o.class, typeof AClass, "object class equality");
assert(o instanceof AClass, "instanceof AClass test");
Class c = o.class;
assertEqual(c.fields.length, 0, "check empty field list");
assertEqual(c.methods.length, 1, "check semi-empty method list (only contains getClassInfo)");
assertEqual(c.superClass, typeof Object, "check super class");
}
void testDynamicInstantiation() {
println("Testing dynamic instantiation");
Class c = typeof AClass();
AClass ac = c.newInstance().as<AClass>;
assertEqual(ac.class, typeof AClass, "dynamically instantiate and check type");
}
void testMethodReflection() {
println("Testing method reflection");
Class c = typeof BClass;
assertEqual(c.superClass, typeof AClass, "check super class");
assertEqual((c.methods[0]).name, "voidMethod", "check method name");
assertEqual((c.methods[0]).returnType, null, "check method return type");
assertEqual((c.methods[0]).parameterTypes.length, 0, "check parameter count");
}
