Running with Code Like with scissors, only more dangerous

6Aug/111

Joining the Jurassic Team

Posted by Rob Paveza

Paul Bartrum graciously just accepted me as a contributor to Jurassic, an open-source JavaScript interpreter written in C#.  I mentioned that I had recently discovered IronJS, but at the time at least, there was no object model – no way of cleanly interfacing .NET code with the script runtime, and frankly, I don’t know F# well enough to meaningfully contribute to that project.  (Please don’t hate on me, functional language junkies).

Jurassic is an exceptionally easy runtime to interface with.  You have to create a script engine, assign it some global variables or functions if you like, and then tell it to execute script.  Very, very easy.  In fact, it took me about an hour to drum up a fairly comprehensive script plugin for JinxBot, which is able to respond to all of BN#’s events (except the clan ones). 

I have several goals and some things I’ve already contributed to the Jurassic source:

  • If you’ve exposed a class to JavaScript using it so far, you’ve probably seen that it’s incredibly easy to expose a method to JavaScript – you decorate it with the [JSFunction] attribute.  Unfortunately, there hadn’t been an analogue for properties, until a commit a couple of days ago.  I added a [JSProperty] attribute, which exposes these properties to JavaScript as accessors.  They are enumerable by default (which means they appear in a for (var … in) loop), and may be opted-in to be configurable.  You can see this functionality in the latest pull, and see it in action in the ScriptEngineTests test class.
  • I also noted that Paul had enabled exposing CLR objects to JavaScript, at least in the source code repository.  In my eyes, this was a security issue, because it could expose the reflection system to the security sandbox.  To account for this, I added the ScriptEngine.EnableExposedClrTypes property, which is false by default.  Attempting to set a global value to a static or instance type while this is false will result in a JavaScriptException being thrown.

Some things that I’ve already started working on and would like to see accomplished:

  • Create a console-based REPL loop.
  • Create a standard library to allow for sandboxed lower-level I/O.  To account for this, I’m planning to add an import(package, [assembly = ‘Jurassic.Library’], [alias]) function to the global object.  For example, import(‘Jurassic.Library.Io’); would import the I/O library, which would enable construction of objects like new io.ByteStream()
  • Create events on ScriptEngine that would allow the engine’s host to intercept, handle, and debug scripting errors.  The biggest use-case I see here is, for example, the debugger statement.  The goal I have here is to be able to create your own debugger, instead of having to launch the system JScript debugger, especially since the JScript debugger is ignorant of the scope and other objects within Jurassic’s engine.
  • Another event I’d like to be able to add is something like EngineAppearsToCycle.  Someone made the point that you could go into the console and type while (true) console.log(‘’) and crash your browser.  The compiler could be refactored somewhat to enable this to be handled.

Eventually, I think it would be cool to refactor the compilation engine to function more like V8 – specifically with its metaclasses.  I’m not particularly adept at building a lexer or parser, but I think Paul has already done a great job, and the engine is still quite fast.  Consequently, this is more of a long-term because-I-can goal than we-need-to-do-it goal, because I honestly don’t think it needs to be done.

I’m excited to be a part of the Jurassic team.  Go check out the project – it’s incredibly easy to add JavaScript scripting to your .NET project!

Filed under: Uncategorized 1 Comment
22Mar/111

Worries over the Future of the .NET Framework

Posted by Rob Paveza

Over the last few years, as exciting as some of the things have been that have come out that make a developer’s time more and more powerful, particularly in the .NET space – LINQ, dynamic programming, lambdas – I’ve become a bit concerned over the evolution of the .NET Framework’s type system.  It seems to me like some things that should be obvious but are not are being left aside.  This post will explore some of the programming issues that I have seen and am predicting.

Automatic Type Conversion for Delegates

Consider a Predicate<T>.  A Predicate<T> delegate accepts a single parameter of type T and returns a Boolean value, true or false, indicating whether that item matched some condition.

List<int> numbers = new List<int> { 1, 2, 5, -20, 10, -5, -3, 0 };
Predicate<int> isPositive = n => n > 0;
List<int> positives = numbers.FindAll(isPositive);


In the code here, I’ve used a lambda expression to indicate that the method generated for the lambda expression should be assignable to a type of Predicate<int>.  Fortunately, C# doesn’t allow you to assign a lambda to an implicit variable (a var), but consider that I could have also written:

List<int> positives = numbers.Where(n => n > 0).ToList();

Note how the lambda expression is exactly the same, and the two pieces of code would produce identical auto-generated methods, yet I couldn’t use numbers.Where(isPositive) because Where takes a Func<T, bool>, and not a Predicate<T>.

So what’s wrong with this?  Hopefully, you can see that it would be reasonable to say that a Func<T, bool> is a Predicate<T>, and that a Predicate<T> is a Func<T, bool>.  That is, delegates in this way have a dual-direction inheritance relationship.

It gets even more interesting when you bring Actions into this.  Actions are delegates that perform some work, accepting 0 or more parameters, but have no return value.  That is, they return void.  Because C# does not allow “Void” to be a type parameter, it is impossible to create an Action<Void>, or an Action<int, Void>.  But, technically speaking, you could have such a construction.

Think about what a delegate really does.  A delegate is the information the compiler needs in order to:

  1. Push all of the parameters onto the stack in the correct order.
  2. Let the callee (the method being called) do its work.
  3. The callee cleans up its own parameters from the stack.
  4. The callee pushes its return value onto the stack, if there is one.
  5. The calling method knows, based on the signature, whether there is a return value on the stack, so it knows the state of the stack.

An Action<T> is really just a specialization of Func<T, Void>.  The two ought to be compatible, and we should stop having so many delegate types polluting the framework and Base Class Library.

Making this Work without Modifying the CLR

Delegate types are defined by IL as types as well.  It may be possible to shoehorn this feature in without modifying the CLR by:

  • Add cast overloads for all delegates to implicitly cast to a Func type that supports its method signature.
  • Add cast overloads for all delegates to be implicitly cast-to from a Func type that supports its method signature.

If I could define something like this in C#, it might look like this:

public delegate bool Predicate<T>(T item)
{
    public static operator implicit Func<T, bool>(Predicate<T> original)
    {
        Func<T, bool> result = _item => original(_item);
        return result;
    }

    public static operator implicit Predicate<T>(Func<T, bool> original)
    {
        Predicate<T> result = _item => original(_item);
        return result;
    }
};

Note that this method uses closures, which would preserve all existing object relationships and not break any object relationship semantics normally required by delegate types.

Numeric Interface for All Primitive Types, Integer Interface for Integral Primitives

Primitive types are the basic structures supported by the CLR:

  • byte/sbyte
  • short/ushort
  • int/uint
  • long/ulong
  • float / double
  • char

String is also included, but that’s a class and heap-allocated, so it’s not really important for the purposes of this discussion.

There are a lot of common operations that you can do with these types.  You can always add them, subtract them, divide them (dividing a char is a weird thing to consider, but is possible).  Actually, if you want to know the position of a given letter in the alphabet, you can just subtract ‘A’ or ‘a’ from it. 

But when it comes to something like a generic type parameter, you can’t say something like:

public class NumberAggregator<T> 
    where T : INumeric
{
    private T _sum = default(T);
    private List<T> _numbers = new List<T>();
    public void Add(T item) 
    { 
        _numbers.Add(item);
        _sum += item;
    }
    // rest of the class
}

This is not possible.  First, there’s no such interface as INumeric, but more importantly, even though the intent of this class is to be able to sum any single size of number, the restriction can be supported by the underlying IL code.  The IL add instruction is a single instruction that does not take into regard the operands (see CIL Instruction Reference, ECMA-335 Partition III page 33). 

You can do a lot of cool things with numbers, particularly integers, that you can’t do with normal types.  You can add, subtract, divide, multiple, bitwise and/or/xor, shift, and invert (I think that covers all of them).  But the generic type system is too limited to allow you to do that.

Type Parameter Restrictions

A long while ago, I talked about the limitation of generics in that they may not support certain types as type parameter constraints, in that article specifically, enumeration types.  Enumeration types would give you similar benefits that I noted in the previous section, about the operations you can perform on numeric types that you generally can’t perform on other types.

While generics in .NET lack some of the power of C++ templates (namely, the ability to create a template that accepts a value, not just a type, as a parameter), they’re still quite good, and they solved a big performance problem in the 1.x CLR of boxing and unboxing primitive types.  However, I still believe that the CLR is limited in a way it does not need to be.  I don’t want to repeat myself, but this particular component is a big one – and a lot of the problems that issue causes could be solved with #2 above.

The .NET Library is Not Unified

Product owners who develop the core CLR need to come together and bridge the gap between incompatible interfaces.  The ISynchronizeInvoke interface was developed and part of the CLR version 1.0.  It was known as the standard way to allow cross-thread communication, most commonly for instances in which a background thread needed to post updates to the main UI thread of a Windows Forms application.

When WPF was released as part of .NET 3.0, it included a completely new model, called Dispatcher, that achieved the exact same purpose.  There was only one problem: Dispatcher doesn’t implement ISynchronizeInvoke, which means that any libraries written for previous versions of .NET, if they had code that needed to synchronize with a user interface, had an incompatible interface.

Writing an adapter for this is not an issue; making a component written for ISynchronizeInvoke work for Dispatcher is fairly trivial.  But this isn’t the only situation in which it’s happened; you have it happening with LINQ to SQL and Entity Framework (a travesty that LINQ to SQL is as closed as it is, because it could have been Entity Framework without all of the enterprisey things that EF has).  You have it within ASP.NET.  In WCF.  How about Silverlight being a reproduction of but completely incompatible implementation of WPF?

Final Thoughts

I still love programming on .NET.  It allows me to spin up applications so quickly and conveniently that I don’t imagine that I’d like to change any time soon.  But on the other hand, sometimes the decisions that the language and platform designers make baffle me. 

So – to my friends who got this far hoping that I’m making my announcement of switching to PHP, Java, or Python – sorry.  You’ll have to wait for another day.  But, hey, Mads, Anders, if we could get some of these changes in – that’d be great!

Filed under: Uncategorized 1 Comment
6Aug/100

Cool Dynamic Code and Talking at AZDNUG on August 10

Posted by Rob Paveza

I’ll be giving a talk next Tuesday, August 10 at the AZ .NET User Group where I’ll be giving a brief treatment on C# 4.0’s new features and primarily be talking about the cool stuff you can do with dynamic code in C#. 

To whet your appetite, here’s some of the code we’ll be reviewing next week:

        static void Main(string[] args)
        {
            string xmlPath = Path.Combine(Environment.CurrentDirectory, "SampleBooks.xml");
            dynamic xml = new DynamicXml(xmlPath);

            foreach (dynamic child in xml)
            {
                string id = child.id;
                Console.WriteLine("BOOK ID: {0}", id);
                Console.WriteLine(child);
            }

            xml.books.SetDefaultIdentifier("id");
            dynamic vs7 = xml.books["bk112"];
            Console.WriteLine("VS7 Book:");
            Console.WriteLine(vs7);

            Console.WriteLine("Title: {0}", xml.books["bk107"].title);

            xml.books["bk113"] = new { Title = "This is a test", 
                  Description = "This is me adding a new anonymous object " +
                  "to the property of a dynamic object by calling SetIndex.", 
                  Author = "Rob Paveza" };
            xml.SaveAs(Path.Combine(Environment.CurrentDirectory, 
                  "SampleBooks-Output.xml"));

            xml.books["bk113"] = new { Title = "This is a replacement", 
                  Description = "This is me replacing an existing dynamic " +
                  "object's property with a new one by calling SetIndex.", 
                  Author = "Rob Paveza" };
            xml.SaveAs(Path.Combine(Environment.CurrentDirectory, 
                  "SampleBooks-Output2.xml"));

            Console.ReadLine();
        }

The user group is meeting at the Microsoft district office at 2929 N. Central Ave., Phoenix (just north of Thomas on Central).  It’ll be on the 14th floor.  I believe pizza will be served.  More info at AZGroups.org

I hope to see you there!

Filed under: Uncategorized No Comments