It was almost 10 am when I finished hacking this morning. Got some coffee, then drove to university.
Sounds like a normal student's day, but not for me - for me it was more like the first day at university after no longer being a student or something like that. Now being a full time hacker, I just went there to say goodbye to everyone. When I arrived there, I realized that I could really feel happy because of this - university is far from what it used to be when I started studying back in '96.
First of all, it's almost impossible to find any parking space - if you do find something which looks like one, well, you quickly realize that a lot of today's students urgently need to go back to driver's school - and learn how to park a car without consuming two or more parking spaces. Thought of having a second breakfast in the cafeteria, but no ... - it takes like forever to get something to eat or drink and then it's so overcrowded, dirty and people are smoking everywhere.
Walked around a bit and then decided to take the more expensive food in the cafeteria 'cause I just didn't feel like waiting in a queue for half an hour or so. Well, it was really expensive compared to Burger King or the local pizza service - payed almost EUR 8 with the salad, coffe and a dessert and it didn't taste very good.
Realized that it's a real nightmare to find a free table - most tables are already occupied and the ones which are not are full with other people's garbage. To make it worse, people are smoking all around you and you don't really feel compfortable. So, before I could eat, I found myself cleaning the table from other people's garbage. A task which isn't easy at all: either you bring the garbage to the dustbin like every good citizen does, but then you quickly realize that the table is already taken by someone else when you come back - or just throw everything onto the floor.
Finally finished eating - well, about half of it, it didn't taste good enough that I wanted to eat more than neccessary. Then, I just left - leaving the dishes and everything on the table .... "excuse me, sir! You must bring this ..." a staff member complained. My response was something like "f... you, I already cleaned two tables!"
Met a friend outside who was about to go to his class. We talked a bit, then he went inside and I went to my car. A few minutes later, he called me telling me that this class is so overcrowded that he couldn't even fit through the door! Hey, something should tell the fire department that there are four times more people in this room than allowed ...
Finally sat in my car, turned on the engines, but no .... of course, someone was too stupid to drive and had an accident at the exit of the parking lot, so I needed to wait about an hour until police and the tow-away vehicle where there. Found it very amusing to see other people sitting in their cars honking for a few minutes, then went to a pub nearby, got some hot tee and read the newspaper.
About an hour later, the jam was gone and I could finally drive home ....
Back home, I felt really happy that I'm not a student anymore and opened a Bofferding (a very good beer from Luxemburg), time to relax and enjoy my evening :-)
Got up really early today. After checking my mail, I realized that Paolo and Zoltan had a really good idea how to solve these problems with mini. Hacked the whole day on it and finally got it working.
Instead of dealing with MONO_TYPE_VAR and MONO_TYPE_MVAR in mini, we just JIT the method for each instantiation. This creates some overhead since we're creating duplicate machine code for each instantiation, but removes a lot of complexity, so it's just the best and easiest approach for the moment.
Also added two new tests to mcs/tests/ - all tests except gen-12 and gen-21 should now succeed.
As you guys probably already know, this week is PDC week ...
It's currently 11:11 am local time and I hacked all night trying to get at least one of the examples to work. Well, I already realized last week that I could only fix one bug at a time and this strategy really worked out fine for me. However, each time I fixed one problem, another problem showed up - a problem which you could not see before because the problem you just fixed was hiding it ;-)
But hey, that's life of a software developer - and I can live very well with it. I mean, I acually just fixed a problem - there's one problem which is now gone and which'll never show up again, so I actually did something productive ...
However, sometimes you still have the aim and the passion of trying to fix everything at once - just to see one of these higly complex examples actually work. Well, that's fine - as long as you don't get too frustrated if you fail.
Tonight, I finally realized that it's still a very long way until we can actually run these examples - it may even be more difficult than compiling them. The problem is mini and the runtime: we need to add support for generic type and method parameters (MONO_TYPE_VAR and MONO_TYPE_MVAR) before we can run the more complicated examples.
Have a look at the following example:
The problem is the Test (t) call in Foo.Hello() - at the time this method is JITed, we cannot know which type t is - for instance, it could be a reference or a value type.
Hacked the whole night until almost 1 pm on the problem I posted yesterday and I'm now almost done with it. My phone rang a few hours after I finally felt asleep, took a shower and went shopping with a friend. We finally went to Wal Mart, got some French fries and went inside ...
The funny thing is that I just wanted to by a cable and some CD-R's, but then I came home with the biggest television they had :-)
As you can see on the picture, I really enjoyed watching Matrix on this huge screen :-)
While playing around with yesterday's example, I realized that there's another problem which needs to be solved first:
The problem is that gmcs calls ConstructedType.ResolveAsTypeStep on Foo<int> before defining Foo's members. This makes the member lookup for Hello fail.
Today, I watched a really exciting basketball game of our local club, TBB Trier. I was one of the first people who bought tickets last week, so we had excellent seats and the game was exciting until the very last second :-)
Not much news in C# generics land, however. You probably still remember the example I blogged yesterday, the
Adding support for so-called default value expressions wan't really hard. Here's a small example:
The basic idea behind this is that a type parameter can either be a reference or a value type and that you may not know at compile time which one it is. This is also the reason why there is no explicit conversion between null and a type parameter.
Note that you may also use default on an arbitrary type, but the left-hand site of the default value expression must resolve to a type.
A few weeks ago, Miguel pointed me to an URL with C# generics examples: http://www.dina.kvl.dk/~sestoft/gcsharp/.
Today, I finally found the time to have a more in-depth look at them and I was wondering whether we can already compile them with gmcs.
Today, I'll do the reflection stuff for generic methods.
The runtime part was really easy and straightforward so far. There's just one small problem: TypeBuilder.DefineMethod() takes a Type[] array of the method's parameter types - so we need to create the generic parameters before we have the MethodBuilder. To keep things simple, I just added an index field to MonoReflectionGenericParam and added support for it to mono_reflection_define_generic_parameter(). There's now an overloaded version of TypeBuilder.DefineGenericParameter() which takes an index argument.
Adding support to gmcs was a bit more difficult as I already mentioned in my last blog. I added a new GenericMethod class (derives from DeclSpace) which is created just before calling new Method (...). We add the type parameters to the GenericMethod and use it as DeclSpace to lookup parameters and local variables.
There's a new
We cannot call generic methods yet, I need to add support to the runtime, class libs and gmcs for this first.
DeclSpace and TypeContainer in the normal mcs and then merged things into gmcs when I was done with it.Method is always in it's class/struct's TypeContainer and this TypeContainer is passed to Method.Define() and Method.Emit(). For generic methods, we need to create a special GenericMethod instance which is derived from DeclSpace and which is used to lookup parameters and locals there.
MONO_TYPE_VAR and MONO_TYPE_MVAR to mini isn't neccessary at all.Type.GetMethods() right wrt. generic instances.
Suppose you have a generic type definition like this:
Now, you want to instantiate Test to Test<int> - and you want to do this in the same assembly. This means that the underlying generic type is actually a TypeBuilder.
We need to consider two things here:
klass->methods, but need to access the tb->methods array on the TypeBuilder instead. We still need to inflate the methods and we should just do this once.
MethodBuilder.
I'm using a small trick to do this: the actual instantiation of a
generic type is done in
mono_reflection_bind_generic_parameters() which is called
from Type.BindGenericParameters(). If the underlying
generic type is a TypeBuilder, we populate
iklass->methods from tb->methods and
tb->ctors.