On Thu, Feb 14, 2008 at 9:15 AM, Edi Weitz edi@agharta.de wrote:
On Wed, 13 Feb 2008 21:49:55 +0100, "Iver Odin Kvello" iverodin@gmail.com wrote:
I tried to muck around with this myself, and discovered the Unbox_Any opcode, present from version 2.0 of the framework; and this also seems to work (see attached patch).
Cool, thanks. Just checking - the IsValueType condition is the correct one?
I think so, but I don't understand this material thoroughly.
http://msdn2.microsoft.com/en-us/library/system.reflection.emit.opcodes.unbo... says that:
When applied to the boxed form of a value type, the unbox.any instruction extracts the value contained within obj (of type O), and is therefore equivalent to unbox followed by ldobj.
When applied to a reference type, the unbox.any instruction has the same effect as castclass typeTok.
But we know it will be a value-type. For ldobj (which is actually present from version 1.0 I see now) the docs say:
The ldobj instruction copies the value pointed to by addrOfValObj (of type &, *, or native int) to the top of the stack. The number of bytes copied depends on the size of the class (as specified by the class parameter). The class parameter is a metadata token representing the value type.
So given that the ld-operation to use only depends on the returnType, it seems to me that it should work. Here are my tests (with the "generic"-thing that I didn't submit a patch for) showing returns of both IsValueType-types and a String:
RDNZL-USER(60): (setf f1 (new (generic "Func" "Int32" "Int32") #'1+)) #<RDNZL::CONTAINER System.Func`2[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] #xdd69738> RDNZL-USER(61): (setf f2 (new (generic "Func" "Int32" "Single") (lambda (x) (coerce x 'single-float)))) #<RDNZL::CONTAINER System.Func`2[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Single, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] #xdd69e68> RDNZL-USER(62): (setf f3 (new (generic "Func" "Int32" "Double") (lambda (x) (* 1.0 x)))) #<RDNZL::CONTAINER System.Func`2[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Double, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] #xdd6a378> RDNZL-USER(63): (setf f4 (new (generic "Func" "Int32" "String") (lambda (x) (format nil "~@r" x)))) #<RDNZL::CONTAINER System.Func`2[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] #xdd6a888> RDNZL-USER(64): (property (invoke "System.Type" "GetType" "System.String") "IsValueType") NIL RDNZL-USER(65): (property (invoke "System.Type" "GetType" "System.Single") "IsValueType") T RDNZL-USER(66): (invoke f1 "Invoke" 5) 6 RDNZL-USER(67): (invoke f2 "Invoke" 5) 5.0 RDNZL-USER(68): (invoke f3 "Invoke" 5) 5.0 RDNZL-USER(69): (invoke f4 "Invoke" 5) "V"
Regards, Iver