In the months and years ahead, dynamic languages are going to take on an increasing important role in the .NET platform. To support this Microsoft is heavily investing in integration between the dynamic languages and the CLR.
Before we get into how that integration works, we have to take a moment to discuss open source. The most important dynamic languages on the .NET platform are IronPython and IronRuby. As both of these are under an open source license, they won't follow the normal schedule for language changes. All open source languages officially supported by Microsoft will have two release cycles. There will be the release early/release often schedule common for open source projects, which of course results in a lot more rollouts. Parallel to this will be the formal, highly tested releases that Microsoft prefers. Companies and developers will have the option use either style of release, as both will use the same code base.
As for integration, is all revolves around the IDynamicObject interface. This acts as a method binder allowing each object to use the semantics of the language it was written in. The languages that will have binders out of the box include IronPython, IronRuby, JScript, and COM. Yes, COM is considered a dynamic language for this purpose of late binding and dynamic method invocation.
In addition to language specific binders, developers can have special rules for just a single class. The easiest way to do this is to start with the abstract class DynamicObject. What follows is a list of actions that can be overridden for custom behavior. As you browse the list you will undoubtedly see some actions not supported directly by the syntax in your language of choice.
- GetMember
- SetMember
- DeleteMember
- UnaryOperation
- BinaryOperation
- Convert
- InvokeMember
- Invoke
- CreateInstance
- GetIndex
- SetIndex
- DeleteIndex
Developers do not have to implement all these methods. They could, for example, create a property bag by simply supporting SetMember and GetMember. And because of the way it was designed, a truly dynamic class can be written in any language, even otherwise statically typed languages like C#.
Originally, IronPython had its own language-specific abstract language tree. As work on the DLR continued it was discovered that the differences between each language was actually quite small. Finally, it was determined that LINQ Expression Trees had almost everything needed to represent any dynamic language.
The missing features, which will be added in .NET 4, are assignment, control flow (loops and goto), and dynamic dispatch nodes. The dynamic dispatch nodes are language specific and used to honor language-specific rules for method calls and overload resolution.
An example of language-specific semantics is the result of multiplying 2 billion by 2. If the expression tree is honoring IronRuby or IronPython semantics, it will return 4 billion. Using C#'s default semantics it will overflowing and VB will default throwing an exception. For those wonder why, IronRuby and IronPython will automatically promote an Int32 to a BigInteger field when an overflow could otherwise occur.
To improve performance, the DLR is using a new call site mechanism. Call sites in the DLR are statically typed representations of a dynamic call based on delegates. Since delegates are not cheap to create, the delegates are cached in a list. For each call, the list is walked until a match is found. If a previously unseen type is seen, a new delegate based on the shared abstract syntax tree for that type is added.
To determine if an argument type has been seen before, each language needs to provider a MetaObject. This holds a check to see if the argument type matches what has been seen in the past and what to do if it does match.
The ability to create new MetaObject allows developers to replace expensive name based hash table lookups with the actually expression tree that represents the method being called. Depending on how it is written, one could even see performance that exceeds what is seen in the static world.