Zoo: A (Still) Imaginary .NET Scripting Language

I’ve always wanted to create my own programming language. About 8 years ago or so I wrote XPROGRAM. A *very* simple interpreted language that allowed you to write very simple graphical programs. I wrote it in Turbo Pascal 6.0 an it ran under MS-DOS. Back then I didn’t know a thing about parsing (I must have been around 12 or so), but it worked, kinda.

Now, years later, I see all these cool features appearing in all these “new” dynamic languages such as Python and Ruby. My problem, as always, is that both these language contain some features that I really like, but none these language contain all of them.

So, now, let’s assume that I would implement my own dynamic language, what features would it have and on what platform would it run? As a platform I’ve chosen .NET (or more generally the CLI, which also includes Mono). The reason is that there’s still a little gap to be filled there. .NET has no “native” dynamic language yet. Java has “Groovy”:http://groovy.codehaus.org, but .NET doesn’t have a real native one. There’s “Boo”:http://boo.codehaus.org, but that’s not a dynamic language, it’s a statically typed one. There’s “IronPython”:http://www.ironpython.com, but that has been built to fully support Python code, not to integrate well into the .NET environment.

Some of the features that the language, which I dubbed Zoo, should support:
* Compiles into CIL (Common Intermediate Language, i.e. “compiled” .NET code).
* Python-like in its handling of object attributes, i.e. there’s no difference between normal attributes and methods, the only difference is that method attributes are callable.
* Define new attributes at runtime.
* The ability extend current classes, where this extension also applies to current instances. So if I would create an instance of a class, and then add methods or attributes to that class, the attributes would also show up in the instance I created before.
* It should be able to take advantage of the current .NET API. And give these classes the same abilities as normal Zoo classes, so it should, for instance, be possible to add new methods to these classes. Think a “timesSayZef method to the int class”:http://www.zefhemel.com/archives/2005/04/29/shining-ruby-extending-classes.

I’ll probably think of more features later, but I have a hard enough time figuring out how you would implement those things.

I’ve started writing some code for the runtime platform. In my implementation everything in Zoo (objects, attributes, methods, functions, classes) is an instance of some subclass of ZooObject. A ZooObject instance has list of attributes associated with it and an Invoke method. What this Invoke method does depends on the kind of ZooObject. For a class it could return an instance of that class, for a function it could execute the function, for some random object it could run a manually defined function.

I’ve also written two simple wrappers for current .NET objects: DotNetObjectWrapper and DotNetMethodWrapper. With the code I got, all I have to do is convert the syntax of Zoo (which I haven’t defined yet) into code like this:

// wrap an instance of the int object
ZooObject obj = new DotNetObjectWrapper(22);
// call the ToString method on the wrapped object
Console.WriteLine(obj["ToString"].Invoke(obj));
// Add a new (predefined) method to the object
obj["PrintAttributes"] = PrintAttributes.GetInstance();
// call this method
obj["PrintAttributes"].Invoke(obj);

Result:

22
PrintAttributes = Zoo.Builtins.PrintAttributes
CompareTo = Zoo.Builtins.DotNetMethodWrapper
Equals = Zoo.Builtins.DotNetMethodWrapper
GetHashCode = Zoo.Builtins.DotNetMethodWrapper
Parse = Zoo.Builtins.DotNetMethodWrapper
Parse = Zoo.Builtins.DotNetMethodWrapper
Parse = Zoo.Builtins.DotNetMethodWrapper
Parse = Zoo.Builtins.DotNetMethodWrapper
ToString = Zoo.Builtins.DotNetMethodWrapper
ToString = Zoo.Builtins.DotNetMethodWrapper
ToString = Zoo.Builtins.DotNetMethodWrapper
ToString = Zoo.Builtins.DotNetMethodWrapper
GetTypeCode = Zoo.Builtins.DotNetMethodWrapper
GetType = Zoo.Builtins.DotNetMethodWrapper

(The duplicate methods are due to multiple overloads that exist.)

This stuff is fun.