I believe Fan generics are feature complete now. I haven't done Map yet, but it will be trivial now that I've got List and Method working.
Final terminology I decided to use:
Generic Type: an open type that uses generic parameters in its signatures. Fan supports three: List, Map, Method
Generic Parameter: a single letter type name used as a placeholder for parameterization
Generic Instance: a parameterized type such as Str[], or |Foo->Int|
Raw Type: the actual type used for a generic parameter (V -> Obj, L -> List, M -> Map)
When generating call signatures, I always use the raw type so that a context free mapping may be done by the Java emitter. Not sure how that will effect .NET's ability to use (or not use) generics.
The typeRefs table includes the qname (podName, typeName). If the type is a generic instance, then an additional sig field provides the normalized signature which pretty much matches Fan source syntax. I added support to Sys.type() to handle any legal type signature including things like "sys::Str[]" or "|->sys::Void|". This is what I now use for type literals and when is/as operators are applied to generic instances (otherwise I map directly to bytecodes).
Perhaps the trickiest aspect of generics is applying them to a closure. When you define a closure, you are both defining a generic instance of sys::Method as well as a subclass of sys::Method. The first is what the user sees - an anonymous method with a parameterized call signature. What goes into fcode however is an synthetic class which subclasses the generic instance signature and implements callX(). The closure initialization site invokes the synthetic's constructor. Since you can't subclass List or Map, this will be the only legal case of subclassing a generic instance. The Java emitter uses this information to figure out what canned version of Method.Indirect to actually subclass (for example |Obj, Int| will be swizzled to subclass from Method.Indirect2). Reflecting an instance of the closure knows nothing about the synthetic class, and only reports it's generic instance type.
All of this is codifed into the sysTest test suite. I've been writing a lot more of my tests in Fan now that I have most of the basic constructs like for and while loops. Not only is it cleaner code, but ensures that all the work I'm doing for tests, will be applicable to the .NET runtime too (especially all this crazy generics shit).
brian Thu 9 Feb 2006
I believe Fan generics are feature complete now. I haven't done Map yet, but it will be trivial now that I've got List and Method working.
Final terminology I decided to use:
Str[]
, or|Foo->Int|
When generating call signatures, I always use the raw type so that a context free mapping may be done by the Java emitter. Not sure how that will effect .NET's ability to use (or not use) generics.
The typeRefs table includes the qname (podName, typeName). If the type is a generic instance, then an additional sig field provides the normalized signature which pretty much matches Fan source syntax. I added support to Sys.type() to handle any legal type signature including things like "sys::Str[]" or "|->sys::Void|". This is what I now use for type literals and when is/as operators are applied to generic instances (otherwise I map directly to bytecodes).
Perhaps the trickiest aspect of generics is applying them to a closure. When you define a closure, you are both defining a generic instance of sys::Method as well as a subclass of sys::Method. The first is what the user sees - an anonymous method with a parameterized call signature. What goes into fcode however is an synthetic class which subclasses the generic instance signature and implements callX(). The closure initialization site invokes the synthetic's constructor. Since you can't subclass List or Map, this will be the only legal case of subclassing a generic instance. The Java emitter uses this information to figure out what canned version of Method.Indirect to actually subclass (for example |Obj, Int| will be swizzled to subclass from Method.Indirect2). Reflecting an instance of the closure knows nothing about the synthetic class, and only reports it's generic instance type.
All of this is codifed into the sysTest test suite. I've been writing a lot more of my tests in Fan now that I have most of the basic constructs like for and while loops. Not only is it cleaner code, but ensures that all the work I'm doing for tests, will be applicable to the .NET runtime too (especially all this crazy generics shit).