Lang.NET Is Helping Game Developers

Back at POPL 06, Tim Sweeny of Epic Games delivered a talk titled “The Next Mainstream Programming Language: A Game Developer’s Perspective“. I imagine he was a little too busy getting Gears of War out the door to attend the Lang.NET Symposium. Too bad, as there were interesting solutions presented that solved two of the issues Tim identified in his his POPL talk.

One of the issues Tim identified is one of Modularity. Gears of War uses the Unreal Engine 3. In other words, UE3 is a game framework and GoW uses that framework. As you might expect, this framework is exposed as a hierarchy of objects. Tim’s example had “Actor” as the base class in the framework hierarchy, with classes like “Player”, “Enemy” and “InventoryItem” inheriting from “Actor”. Then he had game-specific classes like “Dragon” and “Sword” inheriting from the generic “Enemy” class. The problem is that game developers also need to extend the functionality of the framework’s base classes. That is, they need a game-specific version of “Actor” or “InventoryItem” in addition to the game specific subclasses like “Dragon” and “Sword”. Unfortunately, the current generation of languages don’t support this, so game developers often clone the entire framework, which is error-prone and hard to support.

At Lang.NET, Professor Markus Lumpe demonstrated an implementation of the Classbox concept for .NET. Classbox is essentially a solution to the modularity problem Tim identified. They’ve modified C#’s using syntax to apply to individual classes. When using a class in this fashion, you can add extensions to it like new methods and new fields. I’m not sure the scope of these extensions – whether it’s the file with the using clause or the containing assembly – but it’s key to realize this is a local extension. The original framework isn’t modified at all. Within you assembly, the metadata for the extended classes is re-written to include the new extension. So to use Tim’s example, if you extended the framework’s “Actor” class, it would create a YourGame.Actor class that inherited from the Framework.Actor and contained your extensions. Then it would re-write the inheritance metadata (again, only for your assembly) so classes that inherited from Framework.Actor such as Framework.Enemy and Framework.InventoryItem now inherit from YourGame.Actor.

Now I’m sure there are some nefarious uses of this type of inheritance tree hacking. But there are scenarios such as Tim’s Gaming Framework example where this behavior is exactly what you want. I spoke briefly to Markus and at length with Hua Ming, one of Markus’ grad students, about perhaps having a keyword indicating that a class is “classbox enabled” rather than allowing any class to be classboxed in this way. Looking forward to their future work.

Another issue Tim identified was Reliability. He called this problem “If the compiler doesn’t beep, my program should work”. He showed a very simple method to iterate an index array and transform the associated vertex from a vertex array by a provided matrix. A simple function – four lines of code. Yet, the compiler can’t detect null pointer or out-of-bound array access. Adding code to check those runtime conditions would easily double or triple the length of the function. While modern managed languages (C#/VB/Java) have made great strides in eliminating “random memory overwrites” (via type safety) and “memory leaks” (via garbage collection) they don’t help you with these other types of dynamic failures.

At Lang.NET, Microsoft Researcher Mike Barnett demonstrated Spec#. Spec# is a superset of C# that solves these and other types of dynamic errors. The idea, in Mike’s words, is to better bridge developer intent and code by embedding certain specifications into the code itself. Furthermore, it uses a combination of static and data flow analysis to detect the types of dynamic errors Tim described in his talk. So if you took Tim’s simple transform function and fed it into the Spec# compiler, it would warn you of the possible null pointer dereferences. Furthermore, you can eliminate this warning by specifying the caller never pass you a null pointer. This is simply accomplished by adding an exclamation point to the type declaration. In other words, the vertex array method parameter would be declared “Vertex[]! vertices” to indicate you can’t pass in a null array. With Spec#, you can also specify method pre and post conditions, which can solve the out-of-bound array access issue, as well as object invariants, which can specify the valid states an object instance can be in.

I didn’t see Tim give this presentation, I only saw the slides after the fact. But I get the feeling that one of Tim’s points is that game development is extremely cutting edge, and the issues they’re running into now will be mainstream issues in a few years. Good to see language researchers are already well on their way to solving these issues.

The only thing I worry about is when will these ideas make it into mainstream languages? And will they be extensions to existing languages – i.e. will C# 4.0 and VB 10 include classboxing and specifications – or will they be entirely new languages? How much can you improve a language by adding features until it collapses under it’s own weight?

Comments:

You were there? Dang, I should have worn my "The Architect is In" T-Shirt. The more I talked to others, including some people from the BCL Team on Tuesday night, the more that class boxing the way Markus did it seems useful. I rarely want simple inheritance off of an existing class. I usually need to come up with a "parallel" class hierarchy that injects extensions/contractions on the interfaces of the original hierarchy. By the way, that was an awesome symposium. On Monday there was no moment that I was wishing that I could check my e-mail instead. PS: Spec# can be done entirely in the IDE, as far as I can tell. That makes it a very rich idea. I think it will be far more acceptable than formal verification, especially in use on production development projects. (Think if FX cop but with way fewer need for test cases -- the reduction of test-coverage burden should pay for Spec# use hundreds of times over.)
Well, I pulled the trigger a little too quickly there. There are some language tweaks that the Spec# folk put into the C# language (for example) to make it easier to assert that a reference is not allowed to be null, that sort of thing. There are probably decorations that would not require fudging with the language, and then there might be some sugar to make the decorations less painful. But basically, the main work and the game of verifying the assertions is accomplished with an integration into the IDE.