diff --git a/Docs/Thesis.pdf b/Docs/Thesis.pdf
new file mode 100644
Binary files /dev/null and b/Docs/Thesis.pdf differ
diff --git a/Driver/Driver.cs b/Driver/Driver.cs
new file mode 100644
--- /dev/null
+++ b/Driver/Driver.cs
@@ -0,0 +1,1146 @@
+//
+// Salsa .NET Driver
+//
+// Copyright: (c) 2007-2008 Andrew Appleyard
+// Licence:   BSD3 (see LICENSE)
+//
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Net;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+using System.IO;
+using System.Threading;
+
+[assembly: AssemblyTitle("Salsa")]
+[assembly: AssemblyDescription(".NET Bridge for Haskell")]
+[assembly: AssemblyProduct("Salsa")]
+[assembly: AssemblyCopyright("Copyright © 2007-2008 Andrew Appleyard")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+
+// TODO: Consider caching the results of the Get*Stub(string, ...) methods
+//       (although it's not really necessary, Haskell will cache the results).
+
+namespace Salsa
+{
+    public class Driver
+    {
+        internal static AssemblyBuilder _assemblyBuilder;
+        internal static ModuleBuilder _dynamicModuleBuilder;
+        internal static TypeBuilder _stubsTypeBuilder;
+
+        static Driver()
+        {
+            //Console.WriteLine("Using Salsa.dll (version {0})",
+            //    Assembly.GetExecutingAssembly().GetName().Version);
+
+            Trace.Listeners.Add(new ConsoleTraceListener());
+            System.Windows.Forms.Application.EnableVisualStyles();
+
+            _assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
+                new AssemblyName("DynamicAssembly"), AssemblyBuilderAccess.RunAndSave);
+            _dynamicModuleBuilder = _assemblyBuilder.DefineDynamicModule("DynamicModule", "Dynamic.dll");
+            _stubsTypeBuilder = _dynamicModuleBuilder.DefineType("Stubs");
+
+            _inTable.Add(_nextId++, true);  // ObjectId 1
+            _inTable.Add(_nextId++, false); // ObjectId 2
+        }
+
+        public static IntPtr Boot()
+        {
+            // TODO: Accept an option from Salsa for the threading model to use
+            // Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
+
+            return GetPointerToMethod("GetPointerToMethod");
+        }
+
+        /// <summary>
+        /// Returns a native function pointer (as an int) to a stub wrapping the given method.
+        /// </summary>
+        /// <remarks>
+        /// This is the first .NET function called by Haskell, and is called by using the 
+        /// ICLRRuntimeHost.ExecuteInDefaultAppDomain method.
+        /// </remarks>
+        public static IntPtr GetPointerToMethod(string methodName)
+        {
+            //Trace.WriteLine("GetPointerToMethod(" + methodName + ")");
+            //Console.WriteLine("Called on thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
+
+            MethodInfo meth = typeof(Driver).GetMethod(methodName);
+            if (meth == null)
+                throw new ArgumentException("Method not found.", "methodName");
+
+            // Return a delegate pointing to the indicated method (cast to an int 
+            // so we can call this method using ExecuteInDefaultAppDomain)
+            return GenerateMethodStub(meth);
+        }
+
+        #region Entry points
+
+        /// <summary>
+        /// This method is called by Haskell so that the .NET side of the bridge
+        /// has access to the Haskell function 'freeHaskellFunPtr'.
+        /// </summary>
+        public static void SetFreeHaskellFunPtr(IntPtr freeHaskellFunPtr)
+        {
+            if (freeHaskellFunPtr == IntPtr.Zero)
+            {
+                // Clear any previously stored delegate wrapping 'freeHaskellFunPtr'
+                // (this will prevent calls into Haskell from .NET finalizers)
+                FreeHaskellFunPtr = null;
+            }
+            else
+            {
+                // Store the delegate wrapping the 'freeHaskellFunPtr' function passed in
+                FreeHaskellFunPtr =
+                    (FreeHaskellFunPtrDelegate)Marshal.GetDelegateForFunctionPointer(
+                        freeHaskellFunPtr, typeof(FreeHaskellFunPtrDelegate));
+            }
+            Trace.WriteLine(string.Format("SetFreeHaskellFunPtr(0x{0:x})", freeHaskellFunPtr));
+        }
+
+        public static FreeHaskellFunPtrDelegate FreeHaskellFunPtr;
+
+        /// <summary>
+        /// Saves the assembly containing the dynamically generated wrapper methods and 
+        /// delegate classes created during the bridge operation.
+        /// </summary>
+        public static void SaveDynamicAssembly()
+        {
+            _stubsTypeBuilder.CreateType();
+
+            string fileName = Path.GetFileName(_dynamicModuleBuilder.FullyQualifiedName);
+            Console.WriteLine("Saving dynamic assembly: " + fileName);
+            _assemblyBuilder.Save(fileName);
+        }
+
+        /// <summary>
+        /// Given the class, name, and signature of a method or constructor, returns a 
+        /// native function pointer to a delegate that calls the method or constructor
+        /// when invoked.
+        /// </summary>
+        /// <remarks>
+        /// Use a 'methodName' of '.ctor' to obtain a constructor stub.
+        /// </remarks>
+        public static IntPtr GetMethodStub(string className, string methodName,
+            string parameterTypeNames)
+        {
+            if (methodName == ".ctor")
+            {
+                ConstructorInfo con = Util.StringToType(className).GetConstructor(
+                    Util.StringToTypes(parameterTypeNames));
+                return GenerateConstructorStub(con);
+            }
+            else
+            {
+                MethodInfo meth = Util.StringToType(className).GetMethod(
+                    methodName, Util.StringToTypes(parameterTypeNames));
+                return GenerateMethodStub(meth);
+            }
+        }
+
+        /// <summary>
+        /// Given the name of a delegate type, returns a function pointer to a delegate that,
+        /// when called, instantiates delegate instances of the given delegate type when given
+        /// a pointer to a Haskell function.
+        /// </summary>
+        public static IntPtr GetDelegateConstructorStub(string delegateTypeName)
+        {
+            Type delegateType = Util.StringToType(delegateTypeName);
+            return GenerateDelegateConstructorStub(delegateType);
+        }
+
+        /// <summary>
+        /// Given the class and name of a field, returns a native function pointer to a 
+        /// delegate that returns the value of the field when invoked.
+        /// </summary>
+        public static IntPtr GetFieldGetStub(string className, string fieldName)
+        {
+            FieldInfo field = Util.StringToType(className).GetField(fieldName);
+            return GenerateFieldGetStub(field);
+        }
+
+        /// <summary>
+        /// Given the class and name of a field, returns a native function pointer to a 
+        /// delegate that sets the value of the field when invoked.
+        /// </summary>
+        public static IntPtr GetFieldSetStub(string className, string fieldName)
+        {
+            FieldInfo field = Util.StringToType(className).GetField(fieldName);
+            return GenerateFieldSetStub(field);
+        }
+
+        /// <summary>
+        /// Given a value type, returns a native function pointer to a method that 
+        /// boxes values of the given value type.
+        /// </summary>
+        public static IntPtr GetBoxStub(string typeName)
+        {
+            Type typeToBox = Util.StringToType(typeName);
+            return GenerateBoxStub(typeToBox);
+        }
+
+        #endregion
+
+        #region Foreign object references (object in-table)
+
+        /// <summary>
+        /// Maps object identifiers to .NET references.  Allows foreign object identifiers 
+        /// to be dereferenced to .NET object references.  Also ensures that .NET objects 
+        /// referred to from Haskell are kept alive.
+        /// </summary>
+        static Dictionary<int, object> _inTable = new Dictionary<int, Object>();
+
+        static int _nextId = 1;
+
+        /// <summary>
+        /// Registers the given object in the 'in table' and returns the object id
+        /// that was assigned to it.
+        /// </summary>
+        public static int RegisterObject(object o)
+        {
+            if (o == null) 
+                return 0;
+
+            if (o is bool?) // HACK for Nullable<bool>
+            {
+                bool b = (bool)o;
+                return b ? 1 : 2;
+            }
+
+            lock (_inTable)
+            {
+                _inTable.Add(_nextId, o);
+                return _nextId++;
+            }
+        }
+
+        public static object GetObject(int oId)
+        {
+            if (oId == 0) // 0 represents a null reference
+                return null;
+
+            if (oId == 1) // 1 represents boxed true
+                return true; // TODO: Return pre-boxed instance?
+            if (oId == 2) // 0 represents boxed false
+                return false;
+
+            lock (_inTable)
+            {
+                object o;
+                if (_inTable.TryGetValue(oId, out o))
+                    return o;
+                else
+                {
+                    throw new ArgumentException("No object exists with id: " + oId);
+                    // FIXME: This exception will occur in the current implementation of the 
+                    //        bridge if a Haskell garbage collection (and finalization) runs 
+                    //        while a Haskell-implemented delegate is returning an object.
+                    //        Given that this condition tends not to occur with the current
+                    //        implementation of the GHC RTS, and that most delegates in .NET
+                    //        don't return a value at all, I'm leaving the fix for later.
+                }
+            }
+        }
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        public delegate void ReleaseObjectDelegate(int oId);
+        private static ReleaseObjectDelegate _ReleaseObjectDelegate = ReleaseObject;
+
+        public static void ReleaseObject(int oId)
+        {
+            lock (_inTable)
+            {
+                _inTable.Remove(oId);
+            }
+        }
+
+        #endregion
+
+        #region Managed delegate references (function pointer in-table)
+
+        /// <summary>
+        /// Maintains references to any .NET delegates that have a native function pointer
+        /// referring to them (as obtained using Marshal.GetFunctionPointerForDelegate), so 
+        /// that they are not collected prematurely.
+        /// </summary>
+        private static Dictionary<IntPtr, Delegate> _dotNetFunPtrDelegates = new Dictionary<IntPtr, Delegate>();
+
+        /// <summary>
+        /// Returns a native function pointer for calling the given .NET delegate.  A 
+        /// reference to the delegate is stored in _dotNetFunPtrDelegates to prevent
+        /// the delegate from being garbage collected while the function pointer is 
+        /// still being used.
+        /// </summary>
+        private static IntPtr GetDotNetFunPtrForDelegate(Delegate d) // TODO: Perhaps rename 'RegisterDelegate'
+        {
+            IntPtr funPtr = Marshal.GetFunctionPointerForDelegate(d);
+            lock (_dotNetFunPtrDelegates)
+                _dotNetFunPtrDelegates.Add(funPtr, d);
+            return funPtr;
+        }
+
+        /// <summary>
+        /// This method is called to indicate that the given native function pointer 
+        /// will no longer be called from Haskell.  It allows the associated .NET
+        /// delegate to be garbage collected provided there are no other references
+        /// to it.
+        /// </summary>
+        public static void FreeDotNetFunPtr(IntPtr funPtr) // TODO: Perhaps rename 'ReleaseDelegate'
+        {
+            lock (_dotNetFunPtrDelegates)
+                _dotNetFunPtrDelegates.Remove(funPtr);
+        }
+
+        #endregion
+
+        #region Stub method generation
+
+        /// <summary>
+        /// Generates a dynamic method of the given name and signature, containing the instructions 
+        /// produced by 'ilWriter'.  A delegate to the method, is returned to the caller as a native
+        /// function pointer.
+        /// </summary>
+        /// <remarks>
+        /// This method also writes the method to the 'Stubs' class in 'Dynamic.dll' for debugging 
+        /// purposes.
+        /// </remarks>
+        private static IntPtr GenerateDynamicMethod(string methodName,
+            DelegateSignature methodSignature, ILWriterDelegate ilWriter)
+        {
+            if (true)
+            {
+                // Optional: generate an implementation of the stub method inside the 'Stubs'
+                //           class (which is saved to 'Dynamic.dll') for debugging purposes.
+                MethodBuilder savedMethod = _stubsTypeBuilder.DefineMethod(methodName, MethodAttributes.Public,
+                    methodSignature.ReturnType, methodSignature.ParameterTypes);
+                ilWriter(savedMethod.GetILGenerator());
+            }
+
+            // Generate a dynamic method of the given name and signature, and the 
+            // IL instructions given by 'ilWriter', then return a delegate to the
+            // method as a function pointer.
+
+            // [stubReturnType] [classType]_[methodname]([classType] this, [args...]):
+            DynamicMethod method = new DynamicMethod(methodName, methodSignature.ReturnType,
+                methodSignature.ParameterTypes, typeof(Driver));
+            ilWriter(method.GetILGenerator());
+
+            return GetDotNetFunPtrForDelegate(method.CreateDelegate(methodSignature.ToDelegateType()));
+        }
+
+        /// <summary>
+        /// Returns a native function pointer to a wrapper stub that accepts foreign 
+        /// parameters, marshals them, calls the indicated constructor, and returns the
+        /// resulting object instance (marshaled as necessary).
+        /// </summary>
+        /// <remarks>
+        /// The returned function pointer should be freed with 'FreeDotNetFunPtr'.
+        /// When used to construct a value type, 'con' may be null, in which case 
+        /// no constructor is called (the value is just initialised to zero).
+        /// </remarks>
+        public static IntPtr GenerateConstructorStub(ConstructorInfo con)
+        {
+            Type type = con.DeclaringType;
+
+            if (!type.IsValueType && con == null)
+                throw new ArgumentNullException("'con' cannot be null if creating a reference type.");
+
+            // Generate a dynamic method that does the following:
+            //
+            //     Int32 [classType]New([args...])
+            //     {
+            //         [classType] o = new [classType]([args... using GetObject ... ]);
+            //         (box o if it is a value type)
+            //         return Driver.RegisterObject(o);
+            //     }
+
+            // Signature of the stub method returned (as a delegate) by this function
+            DelegateSignature methodSignature = new DelegateSignature(
+                typeof(Int32), 
+                con == null ? Type.EmptyTypes : 
+                              ConvertToStubTypes(Util.MapParametersToTypes(con.GetParameters())));
+
+            return GenerateDynamicMethod(type.Name + "New", methodSignature,
+                delegate(ILGenerator ilg)
+                {
+                    if (con == null) // Initialise object to zero?
+                    {
+                        // Initialise the object in a local variable
+                        ilg.DeclareLocal(type);
+                        ilg.Emit(OpCodes.Ldloca_S, (byte)0);
+                        ilg.Emit(OpCodes.Initobj, type);
+
+                        // Load the object onto the stack
+                        ilg.Emit(OpCodes.Ldloc_0);
+                    }
+                    else // Call object constructor:
+                    {
+                        // Load (and unmarshal), the arguments to the constructor stub
+                        EmitParameterLoading(ilg, 0, con.GetParameters());
+
+                        // Call the constructor, i.e. 'o = new [classType]([unmarshaled args])'
+                        ilg.Emit(OpCodes.Newobj, con);
+                    }
+
+                    // Return the new object (marshaled as an index)
+                    EmitToStub(ilg, type);
+                    ilg.Emit(OpCodes.Ret);
+                });
+        }
+
+        /// <summary>
+        /// Returns a native function pointer to a stub method that calls the given
+        /// method, marshaling arguments as necessary.
+        /// </summary>
+        /// <remarks>
+        /// The returned function pointer should be freed with 'FreeDotNetFunPtr'.
+        /// </remarks>
+        public static IntPtr GenerateMethodStub(MethodInfo meth)
+        {
+            Type classType = meth.DeclaringType;
+
+            // Generate a dynamic method that does the following:
+            //
+            //     [stubReturnType] [classType]_[methodName]([classType] this, [args...])
+            //       OR (if a static method)
+            //     [stubReturnType] [classType]_[methodName]([args...])
+            //     {
+            //         [resultType] r = this.[methodName]([marshaledThis], [marshaled args]);
+            //           OR (if a static method)
+            //         [resultType] r = [className].[methodName]([marshaled args]);
+            //
+            //         return r; OR return Driver.RegisterObject(r);
+            //     }
+
+            // Signature of the stub method returned (as a delegate) by this function
+            DelegateSignature methodSignature = new DelegateSignature(
+                ConvertToStubType(meth.ReturnParameter.ParameterType),
+                meth.IsStatic ? ConvertToStubTypes(Util.MapParametersToTypes(meth.GetParameters())) :
+                    Util.ConcatArray<Type>(
+                        ConvertToStubType(meth.DeclaringType),
+                        ConvertToStubTypes(Util.MapParametersToTypes(meth.GetParameters()))));
+
+            return GenerateDynamicMethod(classType.Name + "_" + meth.Name, methodSignature,
+                delegate(ILGenerator ilg)
+                {
+                    // Load (and unmarshal), the arguments to the method stub, then call the real method
+                    if (meth.IsStatic)
+                    {
+                        EmitParameterLoading(ilg, 0, meth.GetParameters());
+                        ilg.Emit(OpCodes.Call, meth);
+                    }
+                    else
+                    {
+                        EmitParameterLoading(ilg, 0, meth.DeclaringType);
+                        EmitParameterLoading(ilg, 1, meth.GetParameters());
+                        ilg.Emit(OpCodes.Callvirt, meth);
+                    }
+
+                    // Unmarshal and return the result
+                    EmitMarshaledReturn(ilg, meth.ReturnParameter);
+                });
+        }
+
+        /// <summary>
+        /// Instantiates a delegate that, given an IntPtr to a Haskell function, returns a
+        /// delegate instance (of the given delegate type) that wraps this native function
+        /// (and deals with parameter value marshaling and finalization).
+        /// </summary>
+        /// <param name="delegateType">Type of delegate returned by the returned delegate.</param>
+        /// <returns>
+        /// Wrapper delegate that accepts an IntPtr and returns a delegate of the
+        /// indicated type.
+        /// </returns>
+        public static IntPtr GenerateDelegateConstructorStub(Type delegateType)
+        {
+            // Obtain (creating, if necessary) the type of a wrapper class for the delegate
+            Type wrapperType = GetDelegateWrapperType(delegateType);
+
+            DelegateSignature delegateSignature = DelegateSignature.FromDelegateType(delegateType);
+
+            // Generate a dynamic method that does the following:
+            //
+            //     Int32 [delegateType]New(IntPtr funPtr)
+            //     {
+            //         [wrapperType] wrapper = new [wrapperType](funPtr);
+            //         Delegate d = new [delegateType](wrapper.Invoke);
+            //         return Driver.RegisterObject(d);
+            //     }
+
+            // Signature of the method returned (as a delegate) by this function (the
+            // method accepts an IntPtr to a Haskell function and returns an instantiated
+            // .NET delegate for it)
+            DelegateSignature methodSignature = new DelegateSignature(
+                typeof(Int32), new Type[] { typeof(IntPtr) });
+
+            return GenerateDynamicMethod(delegateType.Name + "New", methodSignature,
+                delegate(ILGenerator ilg)
+                {
+                    // wrapper = new [wrapperType](funPtr):
+                    ilg.Emit(OpCodes.Ldarg_0);
+                    ilg.Emit(OpCodes.Newobj, wrapperType.GetConstructor(new Type[] { typeof(IntPtr) }));
+
+                    // Obtain wrapper.Invoke
+                    ilg.Emit(OpCodes.Ldftn, wrapperType.GetMethod("Invoke"));
+
+                    // Delegate d = new [delegateType](wrapper.Invoke):
+                    ilg.Emit(OpCodes.Newobj, delegateType.GetConstructor(new Type[] { typeof(object), typeof(IntPtr) }));
+
+                    // return Driver.RegisterObject(d):
+                    ilg.Emit(OpCodes.Call, MemberInfos.Driver_RegisterObject);
+                    ilg.Emit(OpCodes.Ret);
+                });
+        }
+
+        /// <summary>
+        /// Returns a native function pointer to a stub method that retrieves the value
+        /// of the given static or instance field.
+        /// </summary>
+        /// <remarks>
+        /// The returned function pointer should be freed with 'FreeDotNetFunPtr'.
+        /// </remarks>
+        public static IntPtr GenerateFieldGetStub(FieldInfo field)
+        {
+            // Signature of the stub method returned (as a delegate) by this function
+            DelegateSignature methodSignature = new DelegateSignature(
+                ConvertToStubType(field.FieldType),
+                field.IsStatic ? Type.EmptyTypes : new Type[] { ConvertToStubType(field.DeclaringType) });
+
+            return GenerateDynamicMethod(field.DeclaringType.Name + "_field_get_" + field.Name, methodSignature,
+                delegate(ILGenerator ilg)
+                {
+                    if (field.IsStatic)
+                    {
+                        if (field.IsLiteral)
+                        {
+                            // FIXME: Move literal calculation to the generator, and add
+                            //        support for literal values in the bridge (i.e.
+                            //        values other than 'Obj ObjectId's
+                            object literalValue = field.GetRawConstantValue();
+                            if (literalValue is Int32)
+                                ilg.Emit(OpCodes.Ldc_I4, (Int32)literalValue);
+                        }
+                        else
+                            ilg.Emit(OpCodes.Ldsfld, field);
+                    }
+                    else
+                    {
+                        // Load (and unmarshal) the argument to the method stub, then load the field value
+                        EmitParameterLoading(ilg, 0, field.DeclaringType);
+                        ilg.Emit(OpCodes.Ldfld, field);
+                    }
+
+                    // Unmarshal and return the result
+                    EmitToStub(ilg, field.FieldType);
+                    ilg.Emit(OpCodes.Ret);
+                });
+        }
+
+        /// <summary>
+        /// Returns a native function pointer to a stub method that sets the value
+        /// of the given static or instance field.
+        /// </summary>
+        /// <remarks>
+        /// The returned function pointer should be freed with 'FreeDotNetFunPtr'.
+        /// </remarks>
+        public static IntPtr GenerateFieldSetStub(FieldInfo field)
+        {
+            // Signature of the stub method returned (as a delegate) by this function
+            DelegateSignature methodSignature = new DelegateSignature(
+                typeof(void),
+                field.IsStatic ? 
+                    new Type[] { ConvertToStubType(field.FieldType) } : 
+                    new Type[] { ConvertToStubType(field.DeclaringType), ConvertToStubType(field.FieldType) });
+
+            return GenerateDynamicMethod(field.DeclaringType.Name + "_field_set_" + field.Name, methodSignature,
+                delegate(ILGenerator ilg)
+                {
+                    if (field.IsStatic)
+                    {
+                        // Load (and unmarshal) the field value from the stub call
+                        EmitParameterLoading(ilg, 0, field.FieldType);
+                        ilg.Emit(OpCodes.Stsfld, field);
+                    }
+                    else
+                    {
+                        // Load (and unmarshal) the instance argument and field value from the stub call
+                        EmitParameterLoading(ilg, 0, field.DeclaringType);
+                        EmitParameterLoading(ilg, 1, field.FieldType);
+                        ilg.Emit(OpCodes.Stfld, field);
+                    }
+
+                    ilg.Emit(OpCodes.Ret);
+                });
+        }
+
+        /// <summary>
+        /// Returns a native function pointer to a stub method that returns a 
+        /// reference to the given value (boxing value types as necessary).
+        /// </summary>
+        /// <remarks>
+        /// The returned function pointer should be freed with 'FreeDotNetFunPtr'.
+        /// </remarks>
+        public static IntPtr GenerateBoxStub(Type typeToBox)
+        {
+            // Signature of the stub method returned (as a delegate) by this function
+            DelegateSignature methodSignature = new DelegateSignature(
+                typeof(Int32), new Type[] { ConvertToStubType(typeToBox) });
+
+            return GenerateDynamicMethod("box_" + typeToBox.Name, methodSignature,
+                delegate(ILGenerator ilg)
+                {
+                    // Load the (unboxed) value
+                    EmitParameterLoading(ilg, 0, typeToBox);
+
+                    if (typeToBox.IsValueType)
+                    {
+                        // Box the type value to as an object
+                        ilg.Emit(OpCodes.Box, typeToBox);
+                    }
+
+                    // Marshal the object instance out as an object index
+                    EmitToStub(ilg, typeof(object));
+                    ilg.Emit(OpCodes.Ret);
+                });
+        }
+
+        #endregion
+
+        #region Parameter and result marshaling
+
+        private static bool IsMarshaledByIndex(Type t)
+        {
+            return !t.IsPrimitive && t != typeof(void) && t != typeof(string);
+        }
+
+        /// <summary>
+        /// Returns the type of 'MarshalAs' attribute that should be attached to 
+        /// parameters/results of the given type, if any.
+        /// </summary>
+        private static UnmanagedType? MarshalTypeAs(Type t)
+        {
+            if (t == typeof(string))
+                return UnmanagedType.LPWStr;
+            else
+                return null;
+        }
+
+        /// <summary>
+        /// Given an array of parameters (say of a constructor, or method), returns the 
+        /// array of types that a corresponding wrapper stub would accept.
+        /// </summary>
+        private static Type[] ConvertToStubTypes(Type[] types)
+        {
+            return Util.MapArray<Type, Type>(ConvertToStubType, types);
+        }
+
+        private static Type ConvertToStubType(Type type)
+        {
+            if (IsMarshaledByIndex(type))
+                return typeof(Int32);
+            else
+                return type;
+        }
+
+        /// <summary>
+        /// Emits code (via the given IL generator) to load a single parameter of the given 
+        /// type from the given argument index and on to the stack.  It ensures that object 
+        /// types (which are marshaled by index), are resolved to the appropriate .NET object 
+        /// instance.
+        /// </summary>
+        private static void EmitParameterLoading(ILGenerator ilg, int argumentIndex, Type parameterType)
+        {
+            Util.EmitLdarg(ilg, argumentIndex);
+            EmitFromStub(ilg, parameterType);
+        }
+
+        // Converts a value on the stack from a stub stub to the associated 'real' .NET type
+        /// <summary>
+        /// Emits code to convert a value on the stack from a stub type to the associated
+        /// 'real' .NET type.
+        /// </summary>
+        /// <remarks>
+        /// For example, when called for the 'Button' type, code is emitted to convert an 
+        /// Int32 object identifier into a Button; but when called with the 'String' type 
+        /// no code is emitted at all since the stub type matches the desired .NET type 
+        /// exactly.
+        /// </remarks>
+        private static void EmitFromStub(ILGenerator ilg, Type valueType)
+        {
+            if (IsMarshaledByIndex(valueType))
+            {
+                // [valueType]x = ([valueType])GetObject(value):
+
+                // Call GetObject on the object index to obtain the object instance
+                ilg.Emit(OpCodes.Call, MemberInfos.Driver_GetObject);
+
+                // Cast from Object to the appropriate type for the value (unboxing if necessary)
+                ilg.Emit(OpCodes.Unbox_Any, valueType);
+
+                // Note, the above instruction is equivalent to:
+                //
+                //   if (valueType.IsValueType)
+                //   {
+                //       ilg.Emit(OpCodes.Unbox, valueType);
+                //       ilg.Emit(OpCodes.Ldobj);
+                //   }
+                //   else
+                //       ilg.Emit(OpCodes.Castclass, valueType);
+                //
+            }
+            else
+            {
+                // Leave value as is
+            }
+        }
+
+        /// <summary>
+        /// Emits code (via the given IL generator) to load parameters of the given types 
+        /// from the arguments of the method (starting with 'startingArgument') and on to 
+        /// the stack.  It ensures that object types (which are marshaled by index), are 
+        /// resolved to the appropriate .NET object instance.
+        /// </summary>
+        private static void EmitParameterLoading(ILGenerator ilg, int startingArgument,
+            IEnumerable<ParameterInfo> parameterInfos)
+        {
+            int argumentIndex = startingArgument;
+            foreach (ParameterInfo parameterInfo in parameterInfos)
+            {
+                Type parameterType = parameterInfo.ParameterType;
+                Util.EmitLdarg(ilg, argumentIndex++);
+                EmitFromStub(ilg, parameterType);
+            }
+        }
+
+        private static void EmitToStub(ILGenerator ilg, Type type)
+        {
+            if (IsMarshaledByIndex(type))
+            {
+                if (type.IsValueType)
+                {
+                    // Box the value type for passing it to RegisterObject
+                    ilg.Emit(OpCodes.Box, type);
+                }
+
+                // Marshal the object instance out as an object index, by
+                // calling RegisterObject
+                ilg.Emit(OpCodes.Call, MemberInfos.Driver_RegisterObject);
+            }
+            else
+            {
+                // Leave value as is
+            }
+        }
+
+        /// <summary>
+        /// Emits code (via the given IL generator) to return the value on the top of the
+        /// stack, knowing that its type is given by 'returnParameterInfo'.  It ensures 
+        /// that object types (which are marshaled by index), are returned as an index.
+        /// </summary>
+        private static void EmitMarshaledReturn(ILGenerator ilg, ParameterInfo returnParameterInfo)
+        {
+            Type parameterType = returnParameterInfo.ParameterType;
+            EmitToStub(ilg, parameterType);
+            ilg.Emit(OpCodes.Ret);
+        }
+
+        #endregion
+
+        #region Delegate wrappers
+
+        /// <summary>
+        /// Maintains a cache of the delegate wrapper types that have been generated.
+        /// </summary>
+        private static Dictionary<string, Type> _delegateWrapperTypes =
+            new Dictionary<string, Type>();
+
+        private static Type GetDelegateWrapperType(Type delegateType)
+        {
+            string wrapperTypeName = delegateType.Name + "Wrapper";
+            lock (_delegateWrapperTypes)
+            {
+                Type type;
+                if (!_delegateWrapperTypes.TryGetValue(wrapperTypeName, out type))
+                {
+                    // Could not find wrapper class of appropriate type in the cache: create one
+                    type = CreateDelegateWrapperType(wrapperTypeName, delegateType);
+                    _delegateWrapperTypes.Add(wrapperTypeName, type);
+                }
+                return type;
+            }
+        }
+
+        /// <summary>
+        /// Creates (and returns the type of) a class that wraps a pointer to a
+        /// Haskell function as a .NET delegate.  The class ensures that the
+        /// wrapper function pointer is freed when the delegate is no longer being 
+        /// used by .NET.  It also performs any translation from .NET values to
+        /// interop values (object references are converted to object identifiers).
+        /// </summary>
+        /// <param name="delegateType">Type of delegate produced by the wrapper</param>
+        private static Type CreateDelegateWrapperType(string name, Type delegateType)
+        {
+            // Obtain the signature of the delegate being produced
+            DelegateSignature delegateSignature = DelegateSignature.FromDelegateType(delegateType);
+
+            // Obtain the delegate type of the associated thunk for calling into Haskell
+            Type thunkDelegateType = new DelegateSignature(
+                ConvertToStubType(delegateSignature.ReturnType),
+                ConvertToStubTypes(delegateSignature.ParameterTypes)).ToDelegateType();
+
+            TypeBuilder typeBuilder = _dynamicModuleBuilder.DefineType(name,
+                TypeAttributes.Public | TypeAttributes.Sealed);
+
+            // Define the _thunkDelegate field
+            FieldBuilder thunkDelegateField = typeBuilder.DefineField("_thunkDelegate",
+                thunkDelegateType, FieldAttributes.Private);
+
+            {
+                // Define the constructor for the wrapper type:
+                //
+                //     public DelegateWrapper(IntPtr funPtrToWrap)
+                //     {
+                //         _thunkDelegate = (ThunkDelegate)
+                //             Marshal.GetDelegateForFunctionPointer(
+                //                 funPtrToWrap, typeof(ThunkDelegate));
+                //     }
+
+                ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(
+                    MethodAttributes.Public | MethodAttributes.RTSpecialName,
+                    CallingConventions.Standard, new Type[] { typeof(IntPtr) });
+                ILGenerator ilg = constructorBuilder.GetILGenerator();
+
+                // Call Object's constructor
+                ilg.Emit(OpCodes.Ldarg_0);
+                ilg.Emit(OpCodes.Call, MemberInfos.Object_ctor);
+
+                ilg.Emit(OpCodes.Ldarg_0); // Load this (for the 'stfld' below)
+                ilg.Emit(OpCodes.Ldarg_1); // Load funPtrToWrap
+
+                ilg.Emit(OpCodes.Ldtoken, thunkDelegateType); // Load typeof(ThunkDelegate)
+                ilg.Emit(OpCodes.Call, MemberInfos.Type_GetTypeFromHandle);
+
+                // Call (ThunkDelegate)Marshal.GetDelegateForFunctionPointer(
+                //          funPtrToWrap, typeof(ThunkDelegate))
+                ilg.Emit(OpCodes.Call, MemberInfos.Marshal_GetDelegateForFunctionPointer);
+                ilg.Emit(OpCodes.Castclass, thunkDelegateType);
+
+                // Store in _thunkDelegate
+                ilg.Emit(OpCodes.Stfld, thunkDelegateField);
+
+                ilg.Emit(OpCodes.Ret);
+            }
+
+            {
+                // Define a Finalize method for the wrapper class:
+                //
+                //     ~Delegate()
+                //     {
+                //         if (Driver.FreeHaskellFunPtr != null)
+                //             Driver.FreeHaskellFunPtr(Marshal.GetFunctionPointerForDelegate(
+                //                 _thunkDelegate));
+                //     }
+
+                MethodBuilder finalizeMethod = typeBuilder.DefineMethod("Finalize",
+                    MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.Virtual);
+                finalizeMethod.SetImplementationFlags(MethodImplAttributes.IL | MethodImplAttributes.Managed);
+                ILGenerator ilg = finalizeMethod.GetILGenerator();
+                Label endLabel = ilg.DefineLabel();
+
+                // Obtain the freeHaskellFunPtr delegate
+                ilg.Emit(OpCodes.Ldsfld, MemberInfos.Driver_FreeHaskellFunPtr);
+
+                // Return immediately if the delegate is null
+                ilg.Emit(OpCodes.Ldc_I4_0);
+                ilg.Emit(OpCodes.Beq, endLabel);
+
+                // Obtain the freeHaskellFunPtr delegate (again)
+                ilg.Emit(OpCodes.Ldsfld, MemberInfos.Driver_FreeHaskellFunPtr);
+
+                // Load _thunkDelegate
+                ilg.Emit(OpCodes.Ldarg_0);
+                ilg.Emit(OpCodes.Ldfld, thunkDelegateField);
+
+                // Call Marshal.GetFunctionPointerForDelegate to obtain the original function pointerusing 
+                ilg.Emit(OpCodes.Call, MemberInfos.Marshal_GetFunctionPointerForDelegate);
+
+                // Invoke freeHaskellFunPtr on this function pointer
+                ilg.Emit(OpCodes.Call, MemberInfos.FreeHaskellFunPtrDelegate_Invoke);
+
+                ilg.MarkLabel(endLabel);
+                ilg.Emit(OpCodes.Ret);
+            }
+
+            {
+                // Define an Invoke method that calls _thunkDelegate after marshaling
+                // the arguments as necessary:
+                //
+                //    private void Invoke(...)
+                //    {
+                //        _thunkDelegate(... using RegisterObject as appropriate ...);
+                //    }
+
+                MethodBuilder invokeMethod = typeBuilder.DefineMethod("Invoke",
+                    MethodAttributes.Public, delegateSignature.ReturnType, delegateSignature.ParameterTypes);
+                ILGenerator ilg = invokeMethod.GetILGenerator();
+
+                // Load _thunkDelegate (for calling it later)
+                ilg.Emit(OpCodes.Ldarg_0);
+                ilg.Emit(OpCodes.Ldfld, thunkDelegateField);
+
+                // Load the parameters (and marshal according to type)
+                for (int i = 0; i < delegateSignature.ParameterTypes.Length; i++)
+                {
+                    Util.EmitLdarg(ilg, i + 1);
+                    EmitToStub(ilg, delegateSignature.ParameterTypes[i]);
+                }
+
+                ilg.Emit(OpCodes.Callvirt, thunkDelegateType.GetMethod("Invoke"));
+                EmitFromStub(ilg, delegateSignature.ReturnType);
+                ilg.Emit(OpCodes.Ret);
+            }
+
+            return typeBuilder.CreateType();
+        }
+
+        #endregion
+
+        #region DelegateSignature implementation
+
+        public struct DelegateSignature
+        {
+            private Type _returnType;
+            private Type[] _parameterTypes;
+
+            public Type ReturnType
+            {
+                get { return _returnType; }
+            }
+
+            public Type[] ParameterTypes
+            {
+                get { return _parameterTypes; }
+            }
+
+            public DelegateSignature(Type returnType, Type[] parameterTypes)
+            {
+                _returnType = returnType;
+                _parameterTypes = parameterTypes;
+            }
+
+            public override string ToString()
+            {
+                StringBuilder sb = new StringBuilder();
+                foreach (Type parameter in _parameterTypes)
+                {
+                    sb.Append(parameter.Name);
+                    sb.Append("To");
+                }
+                sb.Append(_returnType.Name);
+                return sb.ToString();
+            }
+
+            public static DelegateSignature FromDelegateType(Type delegateType)
+            {
+                MethodInfo invokeMethod = delegateType.GetMethod("Invoke");
+                return new DelegateSignature(
+                    invokeMethod.ReturnType,
+                    Util.MapParametersToTypes(invokeMethod.GetParameters()));
+            }
+
+            #region Delegate creation
+
+            /// <summary>
+            /// Maintains a cache of the delegate types that have been generated.
+            /// </summary>
+            private static Dictionary<string, Type> _delegateTypes =
+                new Dictionary<string, Type>();
+
+            /// <summary>
+            /// Returns (after creating, if necessary) a delegate type of the given type signature.
+            /// </summary>
+            public Type ToDelegateType()
+            {
+                string delegateName = ToString() + "Delegate";
+                lock (_delegateTypes)
+                {
+                    Type type;
+                    if (!_delegateTypes.TryGetValue(delegateName, out type))
+                    {
+                        // Could not find delegate of appropriate type in the cache: create one
+                        type = CreateDelegateType(delegateName);
+                        _delegateTypes.Add(delegateName, type);
+                    }
+                    return type;
+                }
+            }
+
+            /// <summary>
+            /// Dynamically creates (and returns the type of) a delegate class with the given 
+            /// name and type signature.
+            /// </summary>
+            private Type CreateDelegateType(string name)
+            {
+                TypeBuilder typeBuilder = Driver._dynamicModuleBuilder.DefineType(name,
+                    TypeAttributes.Class | TypeAttributes.Public |
+                    TypeAttributes.Sealed | TypeAttributes.AnsiClass |
+                    TypeAttributes.AutoClass, typeof(System.MulticastDelegate));
+
+                // Add a '[UnmanagedFunctionPointer(CallingConvention.StdCall)]' attribute to the delegate
+                typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(
+                    typeof(UnmanagedFunctionPointerAttribute).GetConstructor(new Type[] { typeof(CallingConvention) }),
+                    new object[] { CallingConvention.StdCall }));
+
+                ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(
+                    MethodAttributes.RTSpecialName | MethodAttributes.HideBySig |
+                    MethodAttributes.Public, CallingConventions.Standard,
+                    new Type[] { typeof(object), typeof(System.IntPtr) });
+                constructorBuilder.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
+
+                MethodBuilder methodBuilder = typeBuilder.DefineMethod("Invoke", MethodAttributes.Public |
+                    MethodAttributes.HideBySig | MethodAttributes.NewSlot |
+                    MethodAttributes.Virtual,
+                    ReturnType, ParameterTypes);
+                methodBuilder.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed);
+
+                // For the return type and any parameter types
+                for (int i = 0; i < ParameterTypes.Length + 1; i++)
+                {
+                    UnmanagedType? marshalAs;
+                    if (i == 0)
+                        marshalAs = MarshalTypeAs(ReturnType);
+                    else
+                        marshalAs = MarshalTypeAs(ParameterTypes[i - 1]);
+
+                    if (marshalAs != null)
+                    {
+                        // Add a MarshalAs attribute to the return/parameter
+                        ParameterBuilder pb = methodBuilder.DefineParameter(i, ParameterAttributes.None, null);
+                        pb.SetCustomAttribute(new CustomAttributeBuilder(
+                                typeof(MarshalAsAttribute).GetConstructor(new Type[] { typeof(UnmanagedType) }),
+                                new object[] { marshalAs.Value }));
+                    }
+                }
+                return typeBuilder.CreateType();
+            }
+
+            #endregion
+        }
+
+        #endregion
+    }
+
+    /// <summary>
+    /// A delegate for the signature of the Haskell function 'freeHaskellFunPtr'.
+    /// </summary>
+    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+    public delegate void FreeHaskellFunPtrDelegate(IntPtr funPtr);
+
+    /// <summary>
+    /// A delegate for code the emits IL instructions on demand.
+    /// </summary>
+    public delegate void ILWriterDelegate(ILGenerator ilg);
+
+    /// <summary>
+    /// Stores references to commonly used reflection object instances.
+    /// </summary>
+    internal static class MemberInfos
+    {
+        public static readonly MethodInfo Type_GetTypeFromHandle =
+            typeof(Type).GetMethod("GetTypeFromHandle");
+
+        public static readonly ConstructorInfo Object_ctor =
+            typeof(object).GetConstructor(Type.EmptyTypes);
+
+        public static readonly MethodInfo Marshal_GetDelegateForFunctionPointer =
+            typeof(Marshal).GetMethod("GetDelegateForFunctionPointer");
+
+        public static readonly MethodInfo Marshal_GetFunctionPointerForDelegate =
+            typeof(Marshal).GetMethod("GetFunctionPointerForDelegate");
+
+        public static readonly MethodInfo Marshal_StringToHGlobalUni =
+            typeof(Marshal).GetMethod("StringToHGlobalUni");
+
+        public static readonly MethodInfo Marshal_StringToHGlobalAnsi =
+            typeof(Marshal).GetMethod("StringToHGlobalAnsi");
+
+        public static readonly FieldInfo Driver_FreeHaskellFunPtr =
+            typeof(Driver).GetField("FreeHaskellFunPtr", BindingFlags.Static | BindingFlags.Public);
+
+        public static readonly MethodInfo Driver_RegisterObject =
+            typeof(Driver).GetMethod("RegisterObject", BindingFlags.Static | BindingFlags.Public);
+
+        public static readonly MethodInfo Driver_GetObject =
+            typeof(Driver).GetMethod("GetObject", BindingFlags.Static | BindingFlags.Public);
+
+        public static readonly MethodInfo FreeHaskellFunPtrDelegate_Invoke =
+            typeof(FreeHaskellFunPtrDelegate).GetMethod("Invoke");
+    }
+
+    internal static class Util
+    {
+        public static Type StringToType(string s)
+        {
+            return Type.GetType(s, true);
+        }
+
+        public static Type[] StringToTypes(string s)
+        {
+            return Util.MapArray<string, Type>(delegate(string t)
+                { return StringToType(t); },
+                s.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
+        }
+
+        public static T[] ConcatArray<T>(T[] a, T[] b)
+        {
+            T[] r = new T[a.Length + b.Length];
+            for (int i = 0; i < a.Length; i++)
+                r[i] = a[i];
+            for (int i = 0; i < b.Length; i++)
+                r[a.Length + i] = b[i];
+            return r;
+        }
+
+        public static T[] ConcatArray<T>(T x, T[] b)
+        {
+            T[] r = new T[1 + b.Length];
+            r[0] = x;
+            for (int i = 0; i < b.Length; i++)
+                r[1 + i] = b[i];
+            return r;
+        }
+
+        public static B[] MapArray<A, B>(Func<A, B> f, A[] xs)
+        {
+            B[] r = new B[xs.Length];
+            for (int i = 0; i < xs.Length; i++)
+                r[i] = f(xs[i]);
+            return r;
+        }
+
+        public delegate B Func<A, B>(A x1);
+
+        public static Type[] MapParametersToTypes(ParameterInfo[] parameters)
+        {
+            return MapArray<ParameterInfo, Type>(
+                delegate(ParameterInfo p) { return p.ParameterType; },
+                parameters);
+        }
+
+        public static void EmitLdarg(ILGenerator ilg, int argumentIndex)
+        {
+            if (argumentIndex == 0) ilg.Emit(OpCodes.Ldarg_0);
+            else if (argumentIndex == 1) ilg.Emit(OpCodes.Ldarg_1);
+            else if (argumentIndex == 2) ilg.Emit(OpCodes.Ldarg_2);
+            else if (argumentIndex == 3) ilg.Emit(OpCodes.Ldarg_3);
+            else if (argumentIndex <= 255) ilg.Emit(OpCodes.Ldarg_S, (byte)argumentIndex);
+            else ilg.Emit(OpCodes.Ldarg, (int)argumentIndex);
+        }
+    }
+}
diff --git a/Driver/Driver.proj b/Driver/Driver.proj
new file mode 100644
--- /dev/null
+++ b/Driver/Driver.proj
@@ -0,0 +1,35 @@
+﻿<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+  <!-- Compile 'Driver.hs' into 'Salsa.dll' using the C# compiler -->
+  <Target Name="BuildDriver">
+    <Csc Sources="Driver.cs"
+         TargetType="library"
+         OutputAssembly="Salsa.dll"
+         Optimize="true"
+         FileAlignment="512" />
+  </Target>
+
+  <!-- Run 'Embed.hs' to embed 'Salsa.dll' into a Haskell module -->
+  <Target Name="EmbedDriver" 
+          Inputs="Salsa.dll;Embed.hs"
+          Outputs="Driver.hs"
+          DependsOnTargets="BuildDriver">
+    <Exec Command="runhaskell Embed Salsa.dll > Driver.hs" />
+  </Target>
+
+  <!-- Copy 'Driver.hs' into the Salsa library tree -->
+  <Target Name="CopyDriver"
+          DependsOnTargets="EmbedDriver">
+    <Copy SourceFiles="Driver.hs"
+          DestinationFiles="..\Foreign\Salsa\Driver.hs" />
+  </Target>
+
+  <Target Name="Build" DependsOnTargets="CopyDriver" />
+
+  <Target Name="Clean" >
+    <Delete Files="Salsa.dll" />
+    <Delete Files="Driver.hs" />
+  </Target>
+
+  <Target Name="Rebuild" DependsOnTargets="Clean;Build" />
+</Project>
diff --git a/Driver/Embed.hs b/Driver/Embed.hs
new file mode 100644
--- /dev/null
+++ b/Driver/Embed.hs
@@ -0,0 +1,37 @@
+-----------------------------------------------------------------------------
+-- |
+-- Program     : Embed
+-- Copyright   : (c) 2007-2008 Andrew Appleyard
+-- Licence     : BSD-style (see LICENSE)
+-- 
+-- Generates a Haskell module that contains the binary data of the Salsa
+-- driver assembly (typically, Salsa.dll) as an (unboxed) string literal.  This
+-- is used to embed the driver assembly in every program that uses Salsa.
+--
+-----------------------------------------------------------------------------
+module Main where
+
+import System.Environment
+import qualified Data.ByteString as S
+import Text.Printf
+import Control.Monad
+import Data.Time.LocalTime (getZonedTime)
+
+main :: IO ()
+main = do
+    now <- getZonedTime
+    putStrLn ("-- Generated " ++ show now)
+    putStrLn "module Foreign.Salsa.Driver (driverData) where"
+    putStrLn "import qualified Data.ByteString.Char8 as B"
+    putStrLn "{-# NOINLINE driverData #-}"
+    putStr "driverData = B.pack \""
+    [inputFile] <- getArgs
+    S.readFile inputFile >>= print
+    putStrLn "\""
+
+  where print s = do let (xs,ys) = S.splitAt 20 s 
+                     putStr "\\\n  \\"
+                     mapM_ (\x -> printf "\\x%02x" x) (S.unpack xs)
+                     when (not $ S.null ys) (print ys)
+
+-- vim:set ts=4 sw=4 expandtab:
diff --git a/Driver/README b/Driver/README
new file mode 100644
--- /dev/null
+++ b/Driver/README
@@ -0,0 +1,12 @@
+
+Building:
+
+  To build the driver assembly, run 'msbuild' in the 'Driver' directory.  This
+  will compile Driver.cs into Salsa.dll, embed it as an unpacked byte string in
+  Driver.hs, and then copy it into the Foreign\Salsa directory.
+
+  You can also build the driver by hand:
+
+    csc -filealign:512 -optimize+ -out:Salsa.dll -target:library Driver.cs
+    runhaskell Embed Salsa.dll > ../Salsa/Driver.hs
+
diff --git a/Foreign/Salsa.hs b/Foreign/Salsa.hs
new file mode 100644
--- /dev/null
+++ b/Foreign/Salsa.hs
@@ -0,0 +1,30 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Salsa
+-- Copyright   : (c) 2007-2008 Andrew Appleyard
+-- Licence     : BSD-style (see LICENSE)
+-- 
+-- Salsa: a .NET bridge for Haskell.
+--
+-----------------------------------------------------------------------------
+module Foreign.Salsa (
+    Obj, _Obj,
+    null_, isNull,
+    ( # ), (>>=#),
+    new, invoke, set, get, delegate,
+    AttrOp(..),
+    withCLR, startCLR, stopCLR,
+    Arr,         _Arr,
+    Int32,
+    cast, Coercible,
+    Object_(..), _Object,
+    Type_(..),   _Type,
+    Int32_,      _Int32,
+    String_,     _String
+    ) where
+
+import Foreign.Salsa.Core
+import Foreign.Salsa.Common
+import Foreign.Salsa.CLR
+
+-- vim:set sw=4 ts=4 expandtab:
diff --git a/Foreign/Salsa/Binding.hs b/Foreign/Salsa/Binding.hs
new file mode 100644
--- /dev/null
+++ b/Foreign/Salsa/Binding.hs
@@ -0,0 +1,89 @@
+{-# LANGUAGE ForeignFunctionInterface, TypeSynonymInstances, ScopedTypeVariables #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Foreign.Salsa.Binding
+-- Copyright   : (c) 2007-2008 Andrew Appleyard
+-- Licence     : BSD-style (see LICENSE)
+-- 
+-- Exports data types and functions required by the generated binding files.
+--
+-----------------------------------------------------------------------------
+module Foreign.Salsa.Binding (
+    module Foreign.Salsa.Common,
+    module Foreign.Salsa.Core,
+    module Foreign.Salsa.CLR,
+    module Foreign.Salsa.TypePrelude,
+    module Foreign.Salsa.Resolver,
+    withCWString, CWString, FunPtr, unsafePerformIO, liftM,
+    type_GetType
+    ) where
+
+import Foreign.Salsa.Common
+import Foreign.Salsa.Core
+import Foreign.Salsa.CLR
+import Foreign.Salsa.TypePrelude
+import Foreign.Salsa.Resolver
+
+import Foreign hiding (new)
+import Foreign.C.String
+
+import Control.Monad (liftM)
+
+-- TODO: Perhaps move some/all of this into the generator, so that it can be
+--       CLR-version neutral.
+
+--
+-- Import the System.Type.GetType(String) and System.Type.MakeArrayType(Int32)
+-- methods so they can be used in the implementations of 'typeOf' as produced by
+-- the generator.
+--
+
+type Type_GetType_stub = CWString -> Bool -> IO ObjectId
+foreign import stdcall "dynamic" make_Type_GetType_stub :: FunPtr Type_GetType_stub -> Type_GetType_stub
+
+{-# NOINLINE type_GetType_stub #-}
+type_GetType_stub :: Type_GetType_stub
+type_GetType_stub = make_Type_GetType_stub $ unsafePerformIO $ getMethodStub
+    "System.Type, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" "GetType"
+    "System.String;System.Boolean"
+
+type_GetType typeName = marshalMethod2s type_GetType_stub undefined undefined (typeName, True)
+
+
+type Type_MakeArrayType_stub = ObjectId -> Int32 -> IO ObjectId
+foreign import stdcall "dynamic" make_Type_MakeArrayType_stub :: FunPtr Type_MakeArrayType_stub -> Type_MakeArrayType_stub
+
+{-# NOINLINE type_MakeArrayType_stub #-}
+type_MakeArrayType_stub :: Type_MakeArrayType_stub
+type_MakeArrayType_stub = make_Type_MakeArrayType_stub $ unsafePerformIO $ getMethodStub
+    "System.Type, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" "MakeArrayType"
+    "System.Int32"
+
+-- 
+-- Typeable instances for primitive types
+--
+
+instance Typeable Int32  where typeOf _ = typeOfString "System.Int32"
+instance Typeable String where typeOf _ = typeOfString "System.String"
+instance Typeable Bool   where typeOf _ = typeOfString "System.Boolean"
+instance Typeable Double where typeOf _ = typeOfString "System.Double"
+
+typeOfString :: String -> Obj Type_
+typeOfString s = unsafePerformIO $ do
+--    putStrLn $ "typeOfString: " ++ s
+    type_GetType s
+--    marshalMethod1s type_GetType_stub undefined undefined s
+
+-- Define the typeOf function for arrays by first calling typeOf on the element type,
+-- and then using the Type.MakeArrayType method to return the associated one-dimensional
+-- array type:
+instance Typeable t => Typeable (Arr t) where
+  typeOf _ = unsafePerformIO $
+    marshalMethod1i type_MakeArrayType_stub (typeOf (undefined :: t)) undefined (1 :: Int32)
+    -- Note: this function requires ScopedTypeVariables
+
+-- Define typeOf for reference types in terms of the associated static type.
+instance Typeable t => Typeable (Obj t) where
+  typeOf _ = typeOf (undefined :: t)
+
+-- vim:set sw=4 ts=4 expandtab:
diff --git a/Foreign/Salsa/CLR.hs b/Foreign/Salsa/CLR.hs
new file mode 100644
--- /dev/null
+++ b/Foreign/Salsa/CLR.hs
@@ -0,0 +1,278 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Foreign.Salsa.CLR
+-- Copyright   : (c) 2007-2008 Andrew Appleyard
+-- Licence     : BSD-style (see LICENSE)
+-- 
+-- Provides convenient functions for accessing the CLR, including: loading
+-- the CLR into the process, releasing .NET object references, and obtaining
+-- dynamically-generated stub functions for calling into .NET from Haskell.
+--
+-----------------------------------------------------------------------------
+module Foreign.Salsa.CLR (
+    withCLR,
+    startCLR, stopCLR,
+    ObjectId,
+    releaseObject,
+    getMethodStub,
+    getFieldGetStub,
+    getFieldSetStub,
+    getDelegateConstructorStub,
+    boxString, boxInt32, boxBoolean 
+    ) where
+
+import Data.Int
+import Foreign hiding (new, newForeignPtr)
+import Foreign.C.String
+
+import Foreign.Salsa.CLRHost
+
+-- | Identifies a foreign (.NET) object instance
+type ObjectId = Int32
+
+-- | Starts the .NET execution engine before executing the given IO action, and
+--   finally stopping the execution engine.  This can only be performed once
+--   in a process.
+withCLR :: IO a -> IO a
+withCLR action = do
+    startCLR
+    r <- action
+    stopCLR
+    return r
+
+startCLR :: IO ()
+startCLR = do
+    start_ICorRuntimeHost clrHost
+
+    -- Allow .NET to call into Haskell and free unused function pointer wrappers
+    setFreeHaskellFunPtr 
+
+stopCLR :: IO ()
+stopCLR = do
+    -- saveDynamicAssembly -- (for debugging)
+
+    -- Prevent .NET finalizers from calling into Haskell (and causing access violations)
+    clearFreeHaskellFunPtr
+
+    stop_ICorRuntimeHost clrHost
+    return ()
+
+-- | 'clrHost' stores a reference to the ICLRRuntimeHost for the .NET execution
+--   engine that is hosted in the process.
+{-# NOINLINE clrHost #-}
+clrHost :: ICorRuntimeHost
+clrHost = unsafePerformIO $ corBindToRuntimeEx
+
+
+-- | @'unsafeGetPointerToMethod' m@ returns a function pointer to the method @m@ 
+--  as implemented in the Salsa .NET driver assembly (Salsa.dll).  It is safe only
+--  if the type of the resulting function pointer matches that of the method given.
+unsafeGetPointerToMethod :: String -> IO (FunPtr a)
+unsafeGetPointerToMethod methodName = do
+    result <- withCWString methodName $ \methodName' -> getPointerToMethodRaw methodName'
+    if result == nullFunPtr
+        then error $ "Unable to execute Salsa.dll method '" ++ methodName ++ "'."
+        else return result
+
+{-# NOINLINE getPointerToMethodRaw #-}
+getPointerToMethodRaw :: GetPointerToMethodDelegate a
+getPointerToMethodRaw = makeGetPointerToMethodDelegate $ unsafePerformIO $ loadDriverAndBoot clrHost
+
+type GetPointerToMethodDelegate a = CWString -> IO (FunPtr a)
+foreign import stdcall "dynamic" makeGetPointerToMethodDelegate :: FunPtr (GetPointerToMethodDelegate a) ->
+    GetPointerToMethodDelegate a
+
+
+-- | Releases the .NET object indicated by the given object id.
+{-# NOINLINE releaseObject #-}
+releaseObject :: ObjectId -> IO ()
+releaseObject = makeReleaseObjectDelegate $ unsafePerformIO $ unsafeGetPointerToMethod "ReleaseObject"
+
+type ReleaseObjectDelegate = ObjectId -> IO ()
+foreign import stdcall "dynamic" makeReleaseObjectDelegate :: FunPtr ReleaseObjectDelegate -> ReleaseObjectDelegate
+
+
+-- | Passes a function pointer to the 'freeHaskellFunPtr' function into .NET so
+--   that Haskell FunPtr's can be freed from .NET code.
+setFreeHaskellFunPtr :: IO ()
+setFreeHaskellFunPtr = do
+    funPtr <- wrapFreeHaskellFunPtr freeHaskellFunPtr
+    setFreeHaskellFunPtrRaw funPtr
+    -- Note: since the function passed into .NET may be used by .NET at any
+    --       point until the engine is shutdown, and the engine is only loaded
+    --       once per process, we don't need to free it.
+
+
+-- | Clears the 'freeHaskellFunPtr' pointer on the .NET side to prevent finalizers from
+--   calling into Haskell (and causing access violations).
+clearFreeHaskellFunPtr :: IO ()
+clearFreeHaskellFunPtr = setFreeHaskellFunPtrRaw nullFunPtr
+
+
+{-# NOINLINE setFreeHaskellFunPtrRaw #-}
+setFreeHaskellFunPtrRaw :: (FunPtr (FunPtr a -> IO ()) -> IO ())
+setFreeHaskellFunPtrRaw = makeSetFreeHaskellFunPtrDelegate $ unsafePerformIO $
+    unsafeGetPointerToMethod "SetFreeHaskellFunPtr"
+  
+foreign import stdcall "dynamic" makeSetFreeHaskellFunPtrDelegate ::
+    FunPtr (FunPtr (FunPtr a -> IO ()) -> IO ()) -> (FunPtr (FunPtr a -> IO ()) -> IO ())
+
+foreign import stdcall "wrapper" wrapFreeHaskellFunPtr :: 
+    (FunPtr a -> IO ()) -> IO (FunPtr (FunPtr a -> IO ()))
+
+
+-- | 'saveDynamicAssembly' saves the assembly containing the dynamically-generated
+--   wrapper stubs to disk (for debugging purposes).
+{-# NOINLINE saveDynamicAssembly #-}
+saveDynamicAssembly :: IO ()
+saveDynamicAssembly = makeSaveDynamicAssemblyDelegate $ unsafePerformIO $ unsafeGetPointerToMethod "SaveDynamicAssembly"
+
+type SaveDynamicAssemblyDelegate = IO ()
+foreign import stdcall "dynamic" makeSaveDynamicAssemblyDelegate :: FunPtr SaveDynamicAssemblyDelegate -> SaveDynamicAssemblyDelegate
+
+
+-- | @'getMethodStub' c m s@ returns a function pointer to a function that, when
+--   called, invokes the method with name @m@ and signature @s@ in class @c@.
+--
+--   @s@ should be a semi-colon delimited list of parameter types indicating the
+--   desired overload of the given method.
+getMethodStub :: String -> String -> String -> IO (FunPtr f)
+getMethodStub className methodName parameterTypeNames = do
+    withCWString className $ \className' ->
+        withCWString methodName $ \methodName' ->
+            withCWString parameterTypeNames $ \parameterTypeNames' ->
+                return $ getMethodStubRaw className' methodName' parameterTypeNames'
+
+{-# NOINLINE getMethodStubRaw #-}
+getMethodStubRaw :: GetMethodStubDelegate a
+getMethodStubRaw = makeGetMethodStubDelegate $ unsafePerformIO $ unsafeGetPointerToMethod "GetMethodStub"
+
+type GetMethodStubDelegate a = CWString -> CWString -> CWString -> FunPtr a
+foreign import stdcall "dynamic" makeGetMethodStubDelegate :: FunPtr (GetMethodStubDelegate a) ->
+    (GetMethodStubDelegate a)
+
+
+-- | @'getFieldGetStub' c f@ returns a function pointer to a function that, when
+--   called, gets the value of the field @f@ in class @c@.
+getFieldGetStub :: String -> String -> IO (FunPtr f)
+getFieldGetStub className fieldName = do
+    withCWString className $ \className' ->
+        withCWString fieldName $ \fieldName' ->
+            return $ getFieldGetStubRaw className' fieldName'
+
+{-# NOINLINE getFieldGetStubRaw #-}
+getFieldGetStubRaw :: GetFieldGetStubDelegate a
+getFieldGetStubRaw = makeGetFieldGetStubDelegate $ unsafePerformIO $ unsafeGetPointerToMethod "GetFieldGetStub"
+
+type GetFieldGetStubDelegate a = CWString -> CWString -> FunPtr a
+foreign import stdcall "dynamic" makeGetFieldGetStubDelegate :: FunPtr (GetFieldGetStubDelegate a) ->
+    (GetFieldGetStubDelegate a)
+
+
+-- | @'getFieldSetStub' c f@ returns a function pointer to a function that, when
+--   called, sets the value of the field @f@ in class @c@ to the given value.
+getFieldSetStub :: String -> String -> IO (FunPtr f)
+getFieldSetStub className fieldName = do
+    withCWString className $ \className' ->
+        withCWString fieldName $ \fieldName' ->
+            return $ getFieldSetStubRaw className' fieldName'
+
+{-# NOINLINE getFieldSetStubRaw #-}
+getFieldSetStubRaw :: GetFieldSetStubDelegate a
+getFieldSetStubRaw = makeGetFieldSetStubDelegate $ unsafePerformIO $ unsafeGetPointerToMethod "GetFieldSetStub"
+
+type GetFieldSetStubDelegate a = CWString -> CWString -> FunPtr a
+foreign import stdcall "dynamic" makeGetFieldSetStubDelegate :: FunPtr (GetFieldSetStubDelegate a) ->
+    (GetFieldSetStubDelegate a)
+
+
+-- | @'getDelegateConstructorStub' dt wrapper@ returns an action that, given a
+--   function, will return a reference to a .NET delegate object that calls the
+--   provided function.  The delegate constructed will be of the type @dt@.  
+--   The function @wrapper@ will be called in order to wrap the given function
+--   as a function pointer for passing into .NET.
+getDelegateConstructorStub :: String -> (f -> IO (FunPtr f)) -> IO (f -> IO ObjectId)
+getDelegateConstructorStub delegateTypeName wrapper = do
+    -- Obtain a function pointer to a function that, when called with a
+    -- function pointer compatible with the given wrapper function, returns
+    -- a reference to a .NET delegate object that calls the function.
+    delegateConstructor <- withCWString delegateTypeName $
+        \delegateTypeName' -> getDelegateConstructorStubRaw delegateTypeName' 
+
+    -- Returns a function that accepts a function, 'f' implementing the
+    -- delegate, converts 'f' to a function pointer, and then wraps it
+    -- up as a .NET delegate.
+    return $ \f -> do
+        fFunPtr <- wrapper f
+        (makeDelegateConstructor delegateConstructor) fFunPtr
+
+{-# NOINLINE getDelegateConstructorStubRaw #-}
+getDelegateConstructorStubRaw :: GetDelegateConstructorStubDelegate a
+getDelegateConstructorStubRaw = makeGetDelegateConstructorStubDelegate $ unsafePerformIO $ unsafeGetPointerToMethod "GetDelegateConstructorStub"
+
+type GetDelegateConstructorStubDelegate a = CWString -> IO (FunPtr (FunPtr a -> IO ObjectId))
+foreign import stdcall "dynamic" makeGetDelegateConstructorStubDelegate :: FunPtr (GetDelegateConstructorStubDelegate a) ->
+    (GetDelegateConstructorStubDelegate a)
+
+type DelegateConstructor a = FunPtr a -> IO ObjectId
+foreign import stdcall "dynamic" makeDelegateConstructor :: FunPtr (DelegateConstructor a) -> (DelegateConstructor a)
+
+--
+-- Boxing support
+--
+
+-- | @'getBoxStub' t@ returns a function pointer to a function that, when
+--   called, returns a boxed object reference to the given type.
+getBoxStub :: String -> IO (FunPtr f)
+getBoxStub typeName = do
+    withCWString typeName $ \typeName' -> return $ getBoxStubRaw typeName'
+
+{-# NOINLINE getBoxStubRaw #-}
+getBoxStubRaw :: GetBoxStubDelegate a
+getBoxStubRaw = makeGetBoxStubDelegate $ unsafePerformIO $ unsafeGetPointerToMethod "GetBoxStub"
+
+type GetBoxStubDelegate a = CWString -> FunPtr a
+foreign import stdcall "dynamic" makeGetBoxStubDelegate :: FunPtr (GetBoxStubDelegate a) -> GetBoxStubDelegate a
+
+
+boxString :: String -> IO ObjectId
+boxString s = withCWString s $ \s' -> boxStringStub s'
+
+type BoxStringStub = CWString -> IO ObjectId
+foreign import stdcall "dynamic" makeBoxStringStub :: FunPtr BoxStringStub -> BoxStringStub
+
+{-# NOINLINE boxStringStub #-}
+boxStringStub :: BoxStringStub
+boxStringStub = makeBoxStringStub $ unsafePerformIO $ getBoxStub "System.String"
+
+
+boxInt32 :: Int32 -> IO ObjectId
+boxInt32 = boxInt32Stub
+
+type BoxInt32Stub = Int32 -> IO ObjectId
+foreign import stdcall "dynamic" makeBoxInt32Stub :: FunPtr BoxInt32Stub -> BoxInt32Stub
+
+{-# NOINLINE boxInt32Stub #-}
+boxInt32Stub :: BoxInt32Stub
+boxInt32Stub = makeBoxInt32Stub $ unsafePerformIO $ getBoxStub "System.Int32"
+
+
+boxBoolean :: Bool -> ObjectId
+boxBoolean True  = boxedTrue
+boxBoolean False = boxedFalse
+
+{-# NOINLINE boxedTrue #-}
+boxedTrue  = unsafePerformIO $ boxBooleanStub True
+
+{-# NOINLINE boxedFalse #-}
+boxedFalse = unsafePerformIO $ boxBooleanStub False
+
+type BoxBooleanStub = Bool -> IO ObjectId
+foreign import stdcall "dynamic" makeBoxBooleanStub :: FunPtr BoxBooleanStub -> BoxBooleanStub
+
+{-# NOINLINE boxBooleanStub #-}
+boxBooleanStub :: BoxBooleanStub
+boxBooleanStub = makeBoxBooleanStub $ unsafePerformIO $ getBoxStub "System.Boolean"
+
+-- vim:set ts=4 sw=4 expandtab:
diff --git a/Foreign/Salsa/CLRHost.hs b/Foreign/Salsa/CLRHost.hs
new file mode 100644
--- /dev/null
+++ b/Foreign/Salsa/CLRHost.hs
@@ -0,0 +1,383 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Foreign.Salsa.CLRHost
+-- Copyright   : (c) 2007-2008 Andrew Appleyard
+-- Licence     : BSD-style (see LICENSE)
+-- 
+-- Exposes some of the methods of the ICLRRuntimeHost COM interface, which
+-- can be used to host the the Microsoft CLR in the process, and to execute
+-- code from a .NET assembly.  Includes basic functionality for dealing
+-- with the Microsoft COM.
+--
+-----------------------------------------------------------------------------
+module Foreign.Salsa.CLRHost (
+    corBindToRuntimeEx,
+    start_ICorRuntimeHost,
+    stop_ICorRuntimeHost,
+    loadDriverAndBoot,
+    ICorRuntimeHost
+    ) where
+
+import Data.Word
+import Data.Int
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.Marshal
+import Foreign.C.String
+import System.Win32
+import System.IO
+import Control.Exception (bracket)
+import Unsafe.Coerce (unsafeCoerce)
+import System.IO.Unsafe (unsafePerformIO)
+import qualified Data.ByteString as S
+import Text.Printf
+
+import Foreign.Salsa.Driver
+
+--
+-- Global static functions for hosting the CLR
+--
+
+type ICorRuntimeHost = InterfacePtr
+
+-- | 'corBindToRunTimeEx' loads the CLR execution engine into the process and returns
+--   a COM interface for it.
+corBindToRuntimeEx :: IO ICorRuntimeHost
+corBindToRuntimeEx = do
+    -- Load the 'mscoree' dynamic library into the process.  This is the
+    -- 'stub' library for the .NET execution engine, and is used to load an
+    -- appropriate version of the real runtime via a call to
+    -- 'CorBindToRuntimeEx'.
+    hMscoree <- loadLibrary "mscoree.dll"
+
+    -- Obtain a pointer to the 'CorBindToRuntimeEx' function from mscoree.dll
+    corBindToRuntimeExAddr <- getProcAddress hMscoree "CorBindToRuntimeEx"
+    let corBindToRuntimeEx = makeCorBindToRuntimeEx $ castPtrToFunPtr corBindToRuntimeExAddr
+
+    let clsid_CorRuntimeHost = Guid 0xCB2F6723 0xAB3A 0x11D2 0x9C 0x40 0x00 0xC0 0x4F 0xA3 0x0A 0x3E
+        iid_ICorRuntimeHost  = Guid 0xCB2F6722 0xAB3A 0x11D2 0x9C 0x40 0x00 0xC0 0x4F 0xA3 0x0A 0x3E
+
+    -- Request the shim (mscoree.dll) to load a version of the runtime into the
+    -- process, returning a pointer to an implementation of the ICorRuntimeHost
+    -- for controlling the runtime.
+    with (nullPtr :: ICorRuntimeHost) $ \clrHostPtr -> do
+        -- Call 'corBindToRuntimeEx' to obtain an ICorRuntimeHost 
+        with clsid_CorRuntimeHost $ \refCLSID_CorRuntimeHost -> 
+            with iid_ICorRuntimeHost $ \refIID_ICorRuntimeHost -> 
+                corBindToRuntimeEx nullPtr nullPtr 0 refCLSID_CorRuntimeHost
+                    refIID_ICorRuntimeHost clrHostPtr >>= checkHR "CorBindToRuntimeEx"
+        peek clrHostPtr
+
+type CorBindToRuntimeEx = LPCWSTR -> LPCWSTR -> DWORD -> Ptr CLSID -> Ptr IID -> Ptr ICorRuntimeHost -> IO HResult
+foreign import stdcall "dynamic" makeCorBindToRuntimeEx :: FunPtr CorBindToRuntimeEx -> CorBindToRuntimeEx
+
+
+-- | 'start_ICorRuntimeHost' calls the Start method of the given ICorRuntimeHost interface.
+start_ICorRuntimeHost this = do
+    -- Initialise COM (and the threading model)
+    coInitializeEx nullPtr coInit_ApartmentThreaded
+    -- TODO: Allow the library user to select their desired threading model
+    --       (we use an STA for the time being so we can use GUI libraries).
+
+    f <- getInterfaceFunction 10 makeStart this
+    f this >>= checkHR "ICorRuntimeHost.Start"
+
+type Start = ICorRuntimeHost -> IO HResult
+foreign import stdcall "dynamic" makeStart :: FunPtr Start -> Start
+
+
+-- | 'stop_ICorRuntimeHost' calls the Stop method of the given ICorRuntimeHost interface.
+stop_ICorRuntimeHost this = do
+    f <- getInterfaceFunction 11 makeStop this
+    f this >>= checkHR "ICorRuntimeHost.Stop"
+
+    coUninitialize
+
+type Stop = ICorRuntimeHost -> IO HResult
+foreign import stdcall "dynamic" makeStop :: FunPtr Stop -> Stop
+
+
+-- | 'getDefaultDomain_ICorRuntimeHost' calls the GetDefaultDOmain method of the given
+--   ICorRuntimeHost interface.
+getDefaultDomain_ICorRuntimeHost this = do
+    f <- getInterfaceFunction 13 makeGetDefaultDomain this
+    with (nullPtr :: InterfacePtr) $ \appDomainPtr -> do
+        f this appDomainPtr >>= checkHR "ICorRuntimeHost.GetDefaultDomain"
+        peek appDomainPtr
+
+type GetDefaultDomain = ICorRuntimeHost -> Ptr InterfacePtr -> IO HResult
+foreign import stdcall "dynamic" makeGetDefaultDomain :: FunPtr GetDefaultDomain -> GetDefaultDomain
+
+
+type AppDomain = InterfacePtr -- mscorlib::_AppDomain
+
+-- | 'load_AppDomain' calls mscorlib::_AppDomain.Load_3(SafeArray* rawAssembly, _Assembly** result).
+load_AppDomain this rawAssembly = do
+    f <- getInterfaceFunction 45 makeLoad_AppDomain this
+    with (nullPtr :: Assembly) $ \assemblyPtr -> do
+        f this rawAssembly assemblyPtr >>= checkHR "AppDomain.Load"
+        peek assemblyPtr
+
+type Load_AppDomain = AppDomain -> SafeArray -> Ptr Assembly -> IO HResult
+foreign import stdcall "dynamic" makeLoad_AppDomain :: FunPtr Load_AppDomain -> Load_AppDomain
+
+-- | 'load_AppDomain_2' calls mscorlib::_AppDomain.Load_2(BStr assemblyString, _Assembly** result).
+load_AppDomain_2 this assemblyString = do
+    f <- getInterfaceFunction 44 makeLoad_AppDomain_2 this
+    withBStr assemblyString $ \assemblyString' -> do
+        with (nullPtr :: InterfacePtr) $ \assemblyPtr -> do
+            f this assemblyString' assemblyPtr >>= checkHR "AppDomain.Load"
+            peek assemblyPtr
+
+type Load_AppDomain_2 = AppDomain -> BStr -> Ptr InterfacePtr -> IO HResult
+foreign import stdcall "dynamic" makeLoad_AppDomain_2 :: FunPtr Load_AppDomain_2 -> Load_AppDomain_2
+
+
+type Assembly = InterfacePtr -- mscorlib::_Assembly
+
+-- | 'getType_Assembly' calls mscorlib::_Assembly.GetType_2(BStr name, _Type** result).
+getType_Assembly this name = do
+    f <- getInterfaceFunction 17 makeGetType_Assembly this
+    withBStr name $ \name' ->
+        with (nullPtr :: Type) $ \typePtr -> do
+            f this name' typePtr >>= checkHR "Assembly.GetType"
+            t <- peek typePtr
+            if t == nullPtr then error "Assembly.GetType failed"
+                            else return t
+
+type GetType_Assembly = Assembly -> BStr -> Ptr Type -> IO HResult
+foreign import stdcall "dynamic" makeGetType_Assembly :: FunPtr GetType_Assembly -> GetType_Assembly
+
+
+type Type = InterfacePtr -- mscorlib::_Type
+
+-- | 'invokeMember_Type' calls mscorlib::_Type.InvokeMember_3(BStr name,
+--   BindingFlags invokeAttr, _Binder* binder, Variant target, SafeArray* args,
+--   Variant* result) to invoke a method without a binder, target or any arguments.
+invokeMember_Type this memberName = do
+    f <- getInterfaceFunction 57 {- _Type.InvokeMember_3 -} makeInvokeMember_Type this
+    withBStr memberName $ \memberName' ->
+        with emptyVariant $ \resultPtr -> do
+            f this memberName' 256 {- BindingFlags.InvokeMethod -}
+                nullPtr 0 0 nullPtr resultPtr >>= checkHR "Type.InvokeMember"
+            peek resultPtr
+
+-- Portability note: Type.InvokeMember accepts a by-value variant argument (as its fourth
+--                   argument).  In the declaration below, this is encoded as two Word64
+--                   arguments.
+type InvokeMember_Type = Type -> BStr -> Word32 -> Ptr () -> Word64 -> Word64 -> Ptr () -> Ptr Variant -> IO HResult
+foreign import stdcall "dynamic" makeInvokeMember_Type :: FunPtr InvokeMember_Type -> InvokeMember_Type
+
+
+-- | 'loadDriverAndBoot' loads the Salsa driver assembly into the application domain from 
+--   memory (the binary data is originally stored in 'driverData'), and then invokes the
+--   Boot method (from the Salsa.Driver class) to obtain a function pointer for invoking 
+--   the 'GetPointerToMethod' method.
+loadDriverAndBoot :: ICorRuntimeHost -> IO (FunPtr (CWString -> IO (FunPtr a)))
+loadDriverAndBoot clrHost = do
+    -- Obtain an _AppDomain interface pointer to the default application domain
+    withInterface (getDefaultDomain_ICorRuntimeHost clrHost) $ \untypedAppDomain -> do
+        let iid_AppDomain = Guid 0x05F696DC 0x2B29 0x3663 0xAD 0x8B 0xC4 0x38 0x9C 0xF2 0xA7 0x13
+        withInterface (queryInterface untypedAppDomain iid_AppDomain) $ \appDomain -> do
+
+            -- Create a safe array for the contents of the driver assembly binary
+            bracket (prim_SafeArrayCreateVector varType_UI1 0 (fromIntegral $ S.length driverData))
+                    (prim_SafeArrayDestroy)
+                (\sa -> do
+                    -- Copy the driver assembly data into the safe array
+                    saDataPtr <- with (nullPtr :: Ptr Word8) $ \ptr ->
+                                      prim_SafeArrayAccessData sa ptr >> peek ptr
+                    S.useAsCStringLen driverData $ \(bsPtr,bsLen) -> do
+                        copyBytes saDataPtr (unsafeCoerce bsPtr) bsLen 
+                    prim_SafeArrayUnaccessData sa
+
+                    -- Load the driver assembly into the application domain
+                    withInterface (load_AppDomain appDomain sa) $ \assembly -> do
+
+                        -- Obtain a _Type interface pointer to the Salsa.Driver type
+                        withInterface (getType_Assembly assembly "Salsa.Driver") $ \typ -> do
+
+                            -- Invoke the Boot method of Salsa.Driver to obtain a function
+                            -- pointer to the 'GetPointerToMethod' method
+                            (Variant _ returnValue) <- invokeMember_Type typ "Boot"
+
+                            -- Return a wrapper function for the 'GetPointerToMethod' method
+                            return $ unsafeCoerce returnValue)
+
+{-
+
+-- | 'executeInDefaultAppDomain_ICLRRuntimeHost' calls the ExecuteInDefaultAppDomain
+--   method of the given ICLRRuntimeHost interface.
+executeInDefaultAppDomain_ICLRRuntimeHost :: ICLRRuntimeHost -> String -> String -> String -> String -> IO DWORD
+executeInDefaultAppDomain_ICLRRuntimeHost this assemblyPath typeName methodName argument = do
+    f <- getInterfaceFunction 11 makeExecuteInDefaultAppDomain this
+    with (0 :: DWORD) $ \resultPtr -> do
+        hResult <- withCWString assemblyPath $ \assemblyPath' -> 
+                       withCWString typeName $ \typeName' ->
+                           withCWString methodName $ \methodName' ->
+                               withCWString argument $ \argument' ->
+                                   f this assemblyPath' typeName' methodName' argument' resultPtr
+        peek resultPtr
+
+type ExecuteInDefaultAppDomain = ICLRRuntimeHost -> LPCWSTR -> LPCWSTR -> LPCWSTR -> LPCWSTR -> Ptr DWORD -> IO HResult
+foreign import stdcall "dynamic" makeExecuteInDefaultAppDomain :: FunPtr ExecuteInDefaultAppDomain -> ExecuteInDefaultAppDomain
+
+-}
+
+--
+-- Types and functions for programming the COM
+--
+
+type HResult  = Word32
+type CLSID    = Guid
+type IID      = Guid
+
+-- | 'InterfacePtr' is a pointer to an arbitrary COM interface (which is a pointer to
+--   a vtable of function pointers for the interface methods).
+type InterfacePtr = Ptr (Ptr (FunPtr ()))
+
+
+-- | 'queryInterface' calls the QueryInterface method of the given COM interface.
+queryInterface this iid = do
+    f <- getInterfaceFunction 0 {- QueryInterface -} makeQueryInterface this
+    with (nullPtr :: InterfacePtr) $ \interfacePtr -> do
+        with iid $ \refIID -> f this refIID interfacePtr >>= checkHR "IUnknown.QueryInterface"
+        peek interfacePtr
+
+type QueryInterface = InterfacePtr -> Ptr IID -> Ptr InterfacePtr -> IO HResult
+foreign import stdcall "dynamic" makeQueryInterface :: FunPtr QueryInterface -> QueryInterface
+
+
+-- | 'release' calls the Release method of the given COM interface.
+release this = do
+    f <- getInterfaceFunction 2 {- Release -} makeRelease this
+    f this
+
+type Release = InterfacePtr -> IO Word32
+foreign import stdcall "dynamic" makeRelease :: FunPtr Release -> Release
+
+
+-- | 'withInterface i f' is like 'bracket' but for COM interface pointers, it calls
+--   'release' once the computation is finished.
+withInterface :: (IO InterfacePtr) -> (InterfacePtr -> IO a) -> IO a
+withInterface i = bracket i (\x -> if x == nullPtr then return 0 else release x)
+
+
+-- | 'getInterfaceFunction' @i makeFun obj@ is an action that returns the @i@th function
+--   of the COM interface referred to by @obj@.  The function is returned as a Haskell
+--   function by passing it through @makeFun@.
+getInterfaceFunction :: Int -> (FunPtr a -> b) -> InterfacePtr -> IO b
+getInterfaceFunction index makeFun this = do
+    -- Obtain a pointer to the appropriate element in the vtable for this interface
+    funPtr <- peek this >>= (flip peekElemOff) index
+    -- Cast the function pointer to the expected type, and import it as a Haskell function
+    return $ makeFun $ castFunPtr funPtr
+
+
+foreign import stdcall "CoInitializeEx" coInitializeEx :: Ptr () -> Int32 -> IO HResult
+foreign import stdcall "CoUninitialize" coUninitialize :: IO ()
+
+coInit_MultiThreaded     = 0 :: Int32
+coInit_ApartmentThreaded = 2 :: Int32
+
+data Guid = Guid Word32 Word16 Word16 Word8 Word8 Word8 Word8 Word8 Word8 Word8 Word8 
+    deriving (Show, Eq)
+
+instance Storable Guid where
+    sizeOf    _ = 16
+    alignment _ = 4
+
+    peek guidPtr = do
+        a  <- peek $ plusPtr guidPtr 0 
+        b  <- peek $ plusPtr guidPtr 4
+        c  <- peek $ plusPtr guidPtr 6
+        d0 <- peek $ plusPtr guidPtr 8
+        d1 <- peek $ plusPtr guidPtr 9
+        d2 <- peek $ plusPtr guidPtr 10
+        d3 <- peek $ plusPtr guidPtr 11
+        d4 <- peek $ plusPtr guidPtr 12
+        d5 <- peek $ plusPtr guidPtr 13
+        d6 <- peek $ plusPtr guidPtr 14
+        d7 <- peek $ plusPtr guidPtr 15
+        return $ Guid a b c d0 d1 d2 d3 d4 d5 d6 d7
+
+    poke guidPtr (Guid a b c d0 d1 d2 d3 d4 d5 d6 d7) = do
+        poke (plusPtr guidPtr 0)  a
+        poke (plusPtr guidPtr 4)  b
+        poke (plusPtr guidPtr 6)  c
+        poke (plusPtr guidPtr 8)  d0
+        poke (plusPtr guidPtr 9)  d1
+        poke (plusPtr guidPtr 10) d2
+        poke (plusPtr guidPtr 11) d3
+        poke (plusPtr guidPtr 12) d4
+        poke (plusPtr guidPtr 13) d5
+        poke (plusPtr guidPtr 14) d6
+        poke (plusPtr guidPtr 15) d7
+
+--
+-- Variant Support
+--
+
+data Variant = Variant VarType Word64 deriving (Show, Eq)
+type VarType = Word16
+
+varType_Empty, varType_UI1 :: VarType
+varType_Empty = 0
+varType_UI1   = 17
+
+emptyVariant = Variant varType_Empty 0
+
+instance Storable Variant where
+    sizeOf    _ = 16
+    alignment _ = 8
+
+    peek ptr = do
+        a  <- peek $ plusPtr ptr 0 
+        b  <- peek $ plusPtr ptr 8
+        return $ Variant a b
+
+    poke ptr (Variant a b) = do
+        poke (plusPtr ptr 0) a
+        poke (plusPtr ptr 2) (0 :: Word16)
+        poke (plusPtr ptr 4) (0 :: Word16)
+        poke (plusPtr ptr 6) (0 :: Word16)
+        poke (plusPtr ptr 8) b
+
+--
+-- Safe Array Support
+--
+
+newtype SafeArray = SafeArray (Ptr ()) deriving (Show, Eq)
+
+foreign import stdcall "SafeArrayCreateVector" prim_SafeArrayCreateVector :: VarType -> Int32 -> Word32 -> IO SafeArray
+foreign import stdcall "SafeArrayAccessData"   prim_SafeArrayAccessData   :: SafeArray -> Ptr (Ptr a) -> IO HResult
+foreign import stdcall "SafeArrayUnaccessData" prim_SafeArrayUnaccessData :: SafeArray -> IO HResult 
+foreign import stdcall "SafeArrayDestroy"      prim_SafeArrayDestroy      :: SafeArray -> IO HResult
+
+--
+-- BStr Support
+--
+
+newtype BStr = BStr (Ptr ()) deriving (Show, Eq)
+
+sysAllocString :: String -> IO BStr
+sysAllocString s = withCWString s prim_SysAllocString
+foreign import stdcall "oleauto.h SysAllocString" prim_SysAllocString :: CWString -> IO BStr
+
+sysFreeString :: BStr -> IO ()
+sysFreeString = prim_SysFreeString
+foreign import stdcall "oleauto.h SysFreeString" prim_SysFreeString :: BStr -> IO ()
+
+withBStr :: String -> (BStr -> IO a) -> IO a
+withBStr s = bracket (sysAllocString s) (sysFreeString)
+
+--
+-- HResult Support
+--
+
+checkHR :: String -> HResult -> IO HResult
+checkHR msg 0 = return 0
+checkHR msg r = error $ printf "%s failed (0x%8x)" msg r
+
+-- vim:set ts=4 sw=4 expandtab:
diff --git a/Foreign/Salsa/Common.hs b/Foreign/Salsa/Common.hs
new file mode 100644
--- /dev/null
+++ b/Foreign/Salsa/Common.hs
@@ -0,0 +1,63 @@
+{-# LANGUAGE EmptyDataDecls #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Foreign.Salsa.Common
+-- Copyright   : (c) 2007-2008 Andrew Appleyard
+-- Licence     : BSD-style (see LICENSE)
+-- 
+-- Exports data types and functions that are used throughout the bridge
+-- implementation.
+--
+-----------------------------------------------------------------------------
+module Foreign.Salsa.Common (
+    Obj(..),          _Obj,
+    Null,
+    Object_(..),      _Object,
+    Type_(..),        _Type,
+    Int32,   Int32_,  _Int32,
+    String,  String_, _String,
+    Arr,              _Arr,
+    Array_,           _Array
+    ) where
+
+import Foreign hiding (new, newForeignPtr)
+
+import Foreign.Salsa.TypePrelude
+import Foreign.Salsa.CLR
+
+-- | @Obj a@ represents a .NET object instance of type @a@.
+data Obj a = Obj !ObjectId !(ForeignPtr ()) 
+           | ObjNull
+
+data Null
+
+-- Value-level equivalent of Obj type constructor:
+_Obj :: t -> Obj t
+_Obj _ = undefined
+
+instance Show (Obj a) where
+    show (Obj id _) = "Object(" ++ show id ++ ")"
+    show ObjNull    = "Object(null)"
+
+-- Labels for elementary .NET types
+data Object_ = Object_                  -- System.Object
+data Type_   = Type_                    -- System.Type
+data Array_  = Array_                   -- System.Array
+_Type   = undefined :: Type_
+_Object = undefined :: Object_
+_Array  = undefined :: Array_
+
+-- Synonym labels for the primitive types
+type String_ = String
+type Int32_  = Int32
+_String = undefined :: String_
+_Int32  = undefined :: Int32_
+
+-- | Represents .NET array types of element type @t@.
+data Arr t
+
+-- -- Value-level equivalent of Arr type constructor:
+_Arr :: t -> Arr t
+_Arr t = undefined
+
+-- vim:set sw=4 ts=4 expandtab:
diff --git a/Foreign/Salsa/Core.hs b/Foreign/Salsa/Core.hs
new file mode 100644
--- /dev/null
+++ b/Foreign/Salsa/Core.hs
@@ -0,0 +1,446 @@
+{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, EmptyDataDecls #-}
+{-# LANGUAGE ExistentialQuantification, FlexibleContexts, TypeOperators #-}
+{-# LANGUAGE ScopedTypeVariables, TypeSynonymInstances, FlexibleInstances #-}
+{-# OPTIONS_GHC -fallow-undecidable-instances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Foreign.Salsa.Core
+-- Copyright   : (c) 2007-2008 Andrew Appleyard
+-- Licence     : BSD-style (see LICENSE)
+-- 
+-----------------------------------------------------------------------------
+module Foreign.Salsa.Core where
+
+import Unsafe.Coerce (unsafeCoerce)
+import Foreign.C.String
+import System.Win32
+
+import Foreign hiding (new, newForeignPtr)
+import Foreign.Concurrent (newForeignPtr)
+
+import Foreign.Salsa.Common
+import Foreign.Salsa.TypePrelude
+import Foreign.Salsa.Resolver
+import Foreign.Salsa.CLR
+
+-- Reverse function application
+x # f = f x
+
+-- Binding to the target of a method invocation
+t >>=# m = t >>= ( # m )
+
+null_ :: Obj Null
+null_ = ObjNull
+
+isNull :: Obj a -> Bool
+isNull ObjNull = True
+isNull _       = False
+
+--
+-- Method invocation
+--
+
+-- | @'Candidates' t m@ is a type-level list of the members of a particular
+--   method group, given the type @t@ and method name @m@.  The overload
+--   resolution algorithm chooses the appropriate member of the method group
+--   (from this list) according to the argument types.
+type family Candidates t m
+
+-- Calls 'ResolveMember', converting argument tuples to/from type-level lists,
+-- and passing it the appropriate list of candidate signatures.
+type family Resolve t m args
+type instance Resolve t m args = ListToTuple (ResolveMember (TupleToList args) (Candidates t m))
+
+-- | 'Invoker' provides type-based dispatch to method implementations, and 
+--   a constrainted result type for method invocations.
+class Invoker t m args where 
+    type Result t m args
+    rawInvoke :: t -> m -> args -> Result t m args
+
+-- | @'invoke' t m args@ invokes the appropriate method @m@ in type @t@ given
+--  the tuple of arguments @args@.
+invoke :: forall t m args args'.
+          (Resolve t m args ~ args',
+           Coercible args args',
+           Invoker t m args') =>
+           t -> m -> args -> Result t m args'
+invoke t m args = rawInvoke t m (coerce args :: args')
+
+--
+-- Constructor invocation
+--
+
+data Ctor = Ctor deriving (Show, Eq)
+
+-- | @'new' t args@ invokes the appropriate constructor for the type @t@
+--   given the tuple of arguments @args@, and returns an instance of the
+--   constructed type.
+new t args = invoke t Ctor args
+
+--
+-- Delegate support
+--
+
+class Delegate dt where
+    type DelegateT dt -- ^ High-level function type for the delegate implementation
+
+    -- | @'delegate' dt h@ calls the constructor for the delegate of type @t@, returning
+    --   a .NET delegate object of the same type whose implementation is the Haskell
+    --   function, @h@.
+    delegate :: dt -> (DelegateT dt) -> IO (Obj dt)
+
+
+--
+-- Attribute system for .NET properties and events
+--
+
+-- | @Prop t pn@ represents a .NET property with name @pn@, on the target object/class @t@.
+class Prop t pn where
+    type PropGT t pn -- ^ type of property when retrieved; () if write-only
+    type PropST t pn -- ^ type of property when set; () if read-only
+    setProp :: t -> pn -> PropST t pn -> IO ()
+    getProp :: t -> pn -> IO (PropGT t pn)
+
+-- | @Event t en@ represents a .NET event with name @pn@, on the target object/class @t@.
+class Event t en where
+    type EventT t en -- ^ type of the event delegate
+    addEvent, removeEvent :: t -> en -> EventT t en -> IO ()
+
+infix 0 :==, :=, :=>, :~, :+, :-, :+>, :->
+
+-- | @AttrOp t@ represents a get/set operation on a .NET property, or an
+--   add/remove operation on a .NET event, on a object/class of type @t@.
+data AttrOp t
+    = forall p. (Prop  t p) => p :== (PropST t p)               -- assign value to property (monotyped)
+    | forall p v. (Prop t p, 
+                   ConvertsTo v (PropST t p) ~ TTrue,
+                   Coercible  v (PropST t p)) =>
+                               p := v                           -- assign value to property (w/ implicit conversion)
+    | forall p v. (Prop  t p,
+                 ConvertsTo v (PropST t p) ~ TTrue,
+                 Coercible  v (PropST t p)) =>
+                               p :=> IO v                       -- assign result of IO action to property 
+    | forall p. (Prop  t p) => p :~  (PropGT t p -> PropST t p) -- update property
+    | forall e. (Event t e) => e :+  (EventT t e)               -- add event listener
+    | forall e. (Event t e) => e :-  (EventT t e)               -- remove event listener
+    | forall e. (Event t e) => e :+> IO (EventT t e)            -- add result of IO action to event listeners
+    | forall e. (Event t e) => e :-> IO (EventT t e)            -- remove result of IO action from event listeners
+
+-- | @'get' t p@ retrieves the value of property @p@ on the target object/class @t@.
+get :: Prop t p => t -> p -> IO (PropGT t p)
+get = getProp
+
+-- | @'set' t ops@ applies the operations @ops@ to the object/class @t@.
+set :: forall t. {-Target t =>-} t -> [AttrOp t] -> IO ()
+set t ops = mapM_ applyOp ops
+    where applyOp :: AttrOp t -> IO ()
+          applyOp (p :== v) = setProp t p v
+          applyOp (p :=  v) = setProp t p (coerce v)
+          applyOp (p :=> v) = v >>= (\v -> setProp t p (coerce v))
+          applyOp (p :~  f) = getProp t p >>= setProp t p . f
+          applyOp (e :+  h) = h #   addEvent    t e
+          applyOp (e :-  h) = h #   removeEvent t e
+          applyOp (e :+> h) = h >>= addEvent    t e
+          applyOp (e :-> h) = h >>= removeEvent t e
+
+    -- 
+    -- Note: a lexically scoped type variable is required in the definition of this
+    -- function.  Both the 'forall t.' in the type signature for 'set' and the the
+    -- type signature for 'applyOp' are required to ensure that the 't' variable
+    -- used in 'set' is the same 't' as that used in 'applyOp'.  Without the scoped 
+    -- type variable, GHC is unable to deduce the desired Prop instance for the call
+    -- to 'setProp'.
+    --
+
+
+-- | 'TupleToList t' is the type-level list representation of the tuple @t@
+--   containing marshalable types.  This allows arguments to .NET members to
+--   be passed as tuples, which have a much neater syntax than lists.
+type family TupleToList t
+type instance TupleToList ()             = TNil
+type instance TupleToList (Obj x)        = Obj x  ::: TNil
+type instance TupleToList String         = String ::: TNil
+type instance TupleToList Int32          = Int32  ::: TNil
+type instance TupleToList Bool           = Bool   ::: TNil
+type instance TupleToList Double         = Double ::: TNil
+type instance TupleToList (a,b)          = a ::: b ::: TNil
+type instance TupleToList (a,b,c)        = a ::: b ::: c ::: TNil
+type instance TupleToList (a,b,c,d)      = a ::: b ::: c ::: d ::: TNil
+type instance TupleToList (a,b,c,d,e)    = a ::: b ::: c ::: d ::: e ::: TNil
+-- ...
+
+-- | 'ListToTuple l' is the tuple type associated with the type-level list @l@.
+type family ListToTuple t
+type instance ListToTuple (Error x)                            = Error x -- propagate errors
+type instance ListToTuple TNil                                 = ()
+type instance ListToTuple (a ::: TNil)                         = a
+type instance ListToTuple (a ::: b ::: TNil)                   = (a,b) 
+type instance ListToTuple (a ::: b ::: c ::: TNil)             = (a,b,c)
+type instance ListToTuple (a ::: b ::: c ::: d ::: TNil)       = (a,b,c,d)
+type instance ListToTuple (a ::: b ::: c ::: d ::: e ::: TNil) = (a,b,c,d,e)
+-- ...
+
+--
+-- Type reflection (connects Haskell types to .NET types)
+--
+
+-- | The class 'Typeable' provides access to the underlying .NET type that is 
+--   associated with a given Haskell type.
+class Typeable t where 
+    -- | Returns the .NET System.Type instance for values of type 't'.
+    --   The value of 't' is not evaluated by the function.
+    typeOf :: t -> Obj Type_
+
+-- TODO: Perhaps rename Typeable to Type or SalsaType or Target?
+
+
+--
+-- Value coercion
+--
+
+-- | @'Coercible' from to@ provides a function 'coerce' for implicitly converting
+--   values of type @from@ to @to@.  It applies only to high-level bridge types
+--   (low-level conversions are handled by the marshaling system).  It always
+--   succeeds.
+class Coercible from to where
+    -- | @'coerce' v@ returns the value @v@ implicitly converted to the desired type.
+    coerce :: from -> to
+
+instance Coercible Int32   Int32   where coerce = id
+instance Coercible String  String  where coerce = id
+instance Coercible Bool    Bool    where coerce = id
+instance Coercible Double  Double  where coerce = id
+instance Coercible Int32   Double  where coerce = fromIntegral
+instance Coercible (Obj f) (Obj t) where coerce = unsafeCoerce
+
+instance Coercible String  (Obj t) where
+    coerce s = unsafePerformIO (boxString s >>= unmarshal) -- boxing conversion
+    -- TODO: Ensure that this is sufficiently referentially transparent.
+
+instance Coercible Int32  (Obj t) where
+    coerce i = unsafePerformIO (boxInt32 i >>= unmarshal) -- boxing conversion
+    -- TODO: Ensure that this is sufficiently referentially transparent.
+
+-- Coercible tuples:
+instance Coercible ()      ()      where coerce = id
+instance (Coercible f0 t0, Coercible f1 t1) =>
+    Coercible (f0,f1) (t0,t1) where
+    coerce (f0,f1) = (coerce f0, coerce f1)
+instance (Coercible f0 t0, Coercible f1 t1, Coercible f2 t2) =>
+    Coercible (f0,f1,f2) (t0,t1,t2) where
+    coerce (f0,f1,f2) = (coerce f0, coerce f1, coerce f2)
+-- ...
+
+-- Lift coerce into the IO monad
+instance (Coercible f t) => Coercible f (IO t)  where 
+    coerce = return . coerce
+
+cast v = coerce v
+
+-- Checked implicit conversion:
+convert :: (Coercible from to, ConvertsTo from to ~ TTrue) => from -> to
+convert v = coerce v
+
+-- TODO: Fix up the whole: coerce vs. cast vs. convert thing.
+--       Work out what's required (i.e. implicit/explicit conversions,
+--       checked or unchecked, etc.)
+
+--
+-- Marshaling support
+--
+
+-- For converting between Haskell types and the proxy types used for
+-- communicating with .NET.
+
+-- | The class 'Marshal' allows high-level Haskell types to be converted into 
+--   low-level types when calling into FFI functions.
+class Marshal from to where
+    marshal :: from -> (to -> IO a) -> IO a
+
+instance Marshal String CWString where
+    marshal s = withCWString s
+
+instance Marshal (Obj a) ObjectId where
+    -- | @'marshal' o k@ provides access to the object identifier in @o@ within
+    --   the IO action @k@, ensuring that the .NET object instance is kept alive
+    --   during the action (like 'withForeignPtr' except for .NET objects).
+    marshal (Obj oId fp) k = withForeignPtr fp (\_ -> k oId)
+    marshal ObjNull      k = k 0
+
+instance Marshal Int Int32 where
+    marshal v f = f (toEnum v)
+
+instance Marshal ()     ()     where marshal = ( # )
+instance Marshal String String where marshal = ( # )
+instance Marshal Int32  Int32  where marshal = ( # )
+instance Marshal Bool   Bool   where marshal = ( # )
+instance Marshal Double Double where marshal = ( # )
+
+-- Special case for Nullable<Boolean>
+instance Marshal (Maybe Bool) ObjectId where
+    marshal Nothing      k = k 0 
+    marshal (Just True)  k = k 1
+    marshal (Just False) k = k 2
+
+
+-- | The class 'Unmarshal' allows low-level types returned by FFI functions to
+--   to be converted into high-level Haskell types.
+class Unmarshal from to where
+    unmarshal :: from -> IO to
+
+instance Unmarshal a () where
+    unmarshal _ = return ()
+
+instance Unmarshal ObjectId (Obj a) where
+    -- | @'unmarshal' o@ wraps the .NET object identified by @o@ as an Obj value.
+    -- 'releaseObject' is called with the object identifier when the Obj is
+    -- garbage collected.
+    unmarshal 0   = return ObjNull
+    unmarshal oId = newForeignPtr nullPtr (releaseObject oId) >>= return . Obj oId
+
+instance Unmarshal CWString String where
+    unmarshal s = do
+        s' <- peekCWString s
+        localFree s -- Free the string allocated by the .NET marshaler (use
+                    -- LocalFree for LPWSTRs and SysFreeString for BSTRs)
+        return s'
+
+instance Unmarshal String String where unmarshal = return
+instance Unmarshal Int32  Int32  where unmarshal = return
+instance Unmarshal Bool   Bool   where unmarshal = return
+instance Unmarshal Double Double where unmarshal = return
+
+-- Special case for Nullable<Boolean>
+instance Unmarshal ObjectId (Maybe Bool) where
+    unmarshal id | id == 1 = return $ Just True
+                 | id == 2 = return $ Just False
+                 | id == 0 = return $ Nothing
+                 | otherwise = error "unmarshal: unexpected ObjectId for Maybe Bool"
+
+
+-- TODO: Generate the functions below using Template Haskell (this code is hideous).
+
+-- Generic marshaling functions for instance methods
+-- (marshal the target object and the tuple of arguments then call the given
+--  function and unmarshal the result)
+marshalMethod0i f o _ ()        = marshal o (\o' -> f o') >>= unmarshal
+marshalMethod1i f o _ (a)       = marshal o (\o' -> marshal a (\a' -> f o' a')) >>= unmarshal
+marshalMethod2i f o _ (a,b)     = marshal o (\o' -> marshal a (\a' -> marshal b (\b' -> f o' a' b'))) >>= unmarshal
+marshalMethod3i f o _ (a,b,c)   = marshal o (\o' -> marshal a (\a' -> marshal b (\b' -> marshal c (\c' -> f o' a' b' c')))) >>= unmarshal
+marshalMethod4i f o _ (a,b,c,d) =
+    marshal o (\o' -> marshal a (\a' -> marshal b (\b' -> marshal c (\c' ->
+    marshal d (\d' -> f o' a' b' c' d'))))) >>= unmarshal
+marshalMethod5i f o _ (a1,a2,a3,a4,a5) =
+    marshal o (\o'   -> marshal a1 (\a1' -> marshal a2 (\a2' -> marshal a3 (\a3' ->
+    marshal a4 (\a4' -> marshal a5 (\a5' -> f o' a1' a2' a3' a4' a5')))))) >>= unmarshal
+marshalMethod6i f o _ (a1,a2,a3,a4,a5,a6) =
+    marshal o (\o'   -> marshal a1 (\a1' -> marshal a2 (\a2' -> marshal a3 (\a3' ->
+    marshal a4 (\a4' -> marshal a5 (\a5' -> marshal a6 (\a6' -> 
+    f o' a1' a2' a3' a4' a5' a6'))))))) >>= unmarshal
+marshalMethod7i f o _ (a1,a2,a3,a4,a5,a6,a7) =
+    marshal o (\o'   -> marshal a1 (\a1' -> marshal a2 (\a2' -> marshal a3 (\a3' ->
+    marshal a4 (\a4' -> marshal a5 (\a5' -> marshal a6 (\a6' -> marshal a7 (\a7' ->
+    f o' a1' a2' a3' a4' a5' a6' a7')))))))) >>= unmarshal
+marshalMethod8i f o _ (a1,a2,a3,a4,a5,a6,a7,a8) =
+    marshal o (\o'   -> marshal a1 (\a1' -> marshal a2 (\a2' -> marshal a3 (\a3' ->
+    marshal a4 (\a4' -> marshal a5 (\a5' -> marshal a6 (\a6' -> marshal a7 (\a7' ->
+    marshal a8 (\a8' ->
+    f o' a1' a2' a3' a4' a5' a6' a7' a8'))))))))) >>= unmarshal
+marshalMethod9i f o _ (a1,a2,a3,a4,a5,a6,a7,a8,a9) =
+    marshal o (\o'   -> marshal a1 (\a1' -> marshal a2 (\a2' -> marshal a3 (\a3' ->
+    marshal a4 (\a4' -> marshal a5 (\a5' -> marshal a6 (\a6' -> marshal a7 (\a7' ->
+    marshal a8 (\a8' -> marshal a9 (\a9' ->
+    f o' a1' a2' a3' a4' a5' a6' a7' a8' a9')))))))))) >>= unmarshal
+marshalMethod10i f o _ (a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) =
+    marshal o   (\o'   -> marshal a1  (\a1'  -> marshal a2  (\a2'  -> marshal a3  (\a3'  ->
+    marshal a4  (\a4'  -> marshal a5  (\a5'  -> marshal a6  (\a6'  -> marshal a7  (\a7'  ->
+    marshal a8  (\a8'  -> marshal a9  (\a9'  -> marshal a10 (\a10' ->
+    f o' a1' a2' a3' a4' a5' a6' a7' a8' a9' a10'))))))))))) >>= unmarshal
+marshalMethod11i f o _ (a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) =
+    marshal o   (\o'   -> marshal a1  (\a1'  -> marshal a2  (\a2'  -> marshal a3  (\a3'  ->
+    marshal a4  (\a4'  -> marshal a5  (\a5'  -> marshal a6  (\a6'  -> marshal a7  (\a7'  ->
+    marshal a8  (\a8'  -> marshal a9  (\a9'  -> marshal a10 (\a10' -> marshal a11 (\a11' ->
+    f o' a1' a2' a3' a4' a5' a6' a7' a8' a9' a10' a11')))))))))))) >>= unmarshal
+-- ...
+
+-- Generic marshaling functions for static methods
+-- (marshal the tuple of arguments then call the given function and unmarshal
+--  the result)
+marshalMethod0s f _ _ ()        = f >>= unmarshal
+marshalMethod1s f _ _ (a)       = marshal a (\a' -> f a') >>= unmarshal
+marshalMethod2s f _ _ (a,b)     = marshal a (\a' -> marshal b (\b' -> f a' b')) >>= unmarshal
+marshalMethod3s f _ _ (a,b,c)   = marshal a (\a' -> marshal b (\b' -> marshal c (\c' -> f a' b' c'))) >>= unmarshal
+marshalMethod4s f _ _ (a,b,c,d) =
+    marshal a (\a' -> marshal b (\b' -> marshal c (\c' -> marshal d (\d' ->
+    f a' b' c' d')))) >>= unmarshal
+marshalMethod5s f _ _ (a,b,c,d,e) =
+    marshal a (\a' -> marshal b (\b' -> marshal c (\c' -> marshal d (\d' ->
+    marshal e (\e' -> f a' b' c' d' e'))))) >>= unmarshal
+marshalMethod6s f _ _ (a1,a2,a3,a4,a5,a6) =
+    marshal a1 (\a1' -> marshal a2 (\a2' -> marshal a3 (\a3' -> marshal a4 (\a4' ->
+    marshal a5 (\a5' -> marshal a6 (\a6' -> f a1' a2' a3' a4' a5' a6')))))) >>= unmarshal
+marshalMethod7s f _ _ (a1,a2,a3,a4,a5,a6,a7) =
+    marshal a1 (\a1' -> marshal a2 (\a2' -> marshal a3 (\a3' -> marshal a4 (\a4' ->
+    marshal a5 (\a5' -> marshal a6 (\a6' -> marshal a7 (\a7' ->
+    f a1' a2' a3' a4' a5' a6' a7'))))))) >>= unmarshal
+marshalMethod8s f _ _ (a1,a2,a3,a4,a5,a6,a7,a8) =
+    marshal a1 (\a1' -> marshal a2 (\a2' -> marshal a3 (\a3' -> marshal a4 (\a4' ->
+    marshal a5 (\a5' -> marshal a6 (\a6' -> marshal a7 (\a7' -> marshal a8 (\a8' ->
+    f a1' a2' a3' a4' a5' a6' a7' a8')))))))) >>= unmarshal
+marshalMethod9s f _ _ (a1,a2,a3,a4,a5,a6,a7,a8,a9) =
+    marshal a1 (\a1' -> marshal a2 (\a2' -> marshal a3 (\a3' -> marshal a4 (\a4' ->
+    marshal a5 (\a5' -> marshal a6 (\a6' -> marshal a7 (\a7' -> marshal a8 (\a8' ->
+    marshal a9 (\a9' ->
+    f a1' a2' a3' a4' a5' a6' a7' a8' a9'))))))))) >>= unmarshal
+marshalMethod10s f _ _ (a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) =
+    marshal a1  (\a1'  -> marshal a2  (\a2'  -> marshal a3  (\a3'  -> marshal a4  (\a4'  ->
+    marshal a5  (\a5'  -> marshal a6  (\a6'  -> marshal a7  (\a7'  -> marshal a8  (\a8'  ->
+    marshal a9  (\a9'  -> marshal a10 (\a10' ->
+    f a1' a2' a3' a4' a5' a6' a7' a8' a9' a10')))))))))) >>= unmarshal
+marshalMethod11s f _ _ (a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) =
+    marshal a1  (\a1'  -> marshal a2  (\a2'  -> marshal a3  (\a3'  -> marshal a4  (\a4'  ->
+    marshal a5  (\a5'  -> marshal a6  (\a6'  -> marshal a7  (\a7'  -> marshal a8  (\a8'  ->
+    marshal a9  (\a9'  -> marshal a10 (\a10' -> marshal a11 (\a11' ->
+    f a1' a2' a3' a4' a5' a6' a7' a8' a9' a10' a11'))))))))))) >>= unmarshal
+-- ...
+
+-- Converts a function accepting and returning high-level types, to a function
+-- that takes and returns low-level (base) types.
+
+marshalFn0 f = do
+    o <- f
+    oId <- marshal o return
+    return oId
+
+marshalFn1 f = \a1' -> unmarshal a1' >>= (\a1 -> f a1 >>= flip marshal return)
+
+marshalFn2 f = \f1 f2 -> do
+    t1 <- unmarshal f1
+    t2 <- unmarshal f2
+    r <- f t1 t2
+    --
+    -- FIXME: We might have an issue here when 'r' is an object (Obj).  After
+    -- marshal returns, it is possible that no references to 'r' remain in
+    -- Haskell.  If the finalizer for the object is called before the 
+    -- identifier is returned to .NET and looked up in the in-table, then
+    -- the lookup will fail.  The following code forces this error:
+    --
+    --   marshal r return >>= (\rId -> performGC >> yield >> return rId)
+    --
+    marshal r return
+
+marshalFn3 f = \a1' a2' a3' -> 
+    unmarshal a1' >>= (\a1 -> unmarshal a2' >>= (\a2 -> unmarshal a3' >>= (\a3 ->
+    (f a1 a2 a3 >>= flip marshal return))))
+
+marshalFn4 f = \a1' a2' a3' a4' -> 
+    unmarshal a1' >>= (\a1 -> unmarshal a2' >>= (\a2 -> unmarshal a3' >>= (\a3 ->
+    unmarshal a4' >>= (\a4 -> (f a1 a2 a3 a4 >>= flip marshal return)))))
+
+marshalFn5 f = \a1' a2' a3' a4' a5' -> 
+    unmarshal a1' >>= (\a1 -> unmarshal a2' >>= (\a2 -> unmarshal a3' >>= (\a3 ->
+    unmarshal a4' >>= (\a4 -> unmarshal a5' >>= (\a5 ->
+    (f a1 a2 a3 a5 a5 >>= flip marshal return))))))
+-- ...
+
+-- vim:set sw=4 ts=4 expandtab:
diff --git a/Foreign/Salsa/Driver.hs b/Foreign/Salsa/Driver.hs
new file mode 100644
--- /dev/null
+++ b/Foreign/Salsa/Driver.hs
@@ -0,0 +1,953 @@
+-- Generated 2008-10-06 01:24:30.052 AUS Eastern Daylight Time
+module Foreign.Salsa.Driver (driverData) where
+import qualified Data.ByteString.Char8 as B
+{-# NOINLINE driverData #-}
+driverData = B.pack "\
+  \\x4d\x5a\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xff\xff\x00\x00\xb8\x00\x00\x00\
+  \\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x80\x00\x00\x00\x0e\x1f\xba\x0e\x00\xb4\x09\xcd\x21\xb8\x01\x4c\xcd\x21\x54\x68\
+  \\x69\x73\x20\x70\x72\x6f\x67\x72\x61\x6d\x20\x63\x61\x6e\x6e\x6f\x74\x20\x62\x65\
+  \\x20\x72\x75\x6e\x20\x69\x6e\x20\x44\x4f\x53\x20\x6d\x6f\x64\x65\x2e\x0d\x0d\x0a\
+  \\x24\x00\x00\x00\x00\x00\x00\x00\x50\x45\x00\x00\x4c\x01\x03\x00\x1d\xce\xe8\x48\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x0e\x21\x0b\x01\x08\x00\x00\x42\x00\x00\
+  \\x00\x06\x00\x00\x00\x00\x00\x00\x3e\x61\x00\x00\x00\x20\x00\x00\x00\x80\x00\x00\
+  \\x00\x00\x40\x00\x00\x20\x00\x00\x00\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\
+  \\x04\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\
+  \\x03\x00\x40\x05\x00\x00\x10\x00\x00\x10\x00\x00\x00\x00\x10\x00\x00\x10\x00\x00\
+  \\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x60\x00\x00\
+  \\x53\x00\x00\x00\x00\x80\x00\x00\x60\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x20\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x08\x20\x00\x00\x48\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2e\x74\x65\x78\
+  \\x74\x00\x00\x00\x44\x41\x00\x00\x00\x20\x00\x00\x00\x42\x00\x00\x00\x02\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x60\x2e\x72\x73\x72\
+  \\x63\x00\x00\x00\x60\x03\x00\x00\x00\x80\x00\x00\x00\x04\x00\x00\x00\x44\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x40\x2e\x72\x65\x6c\
+  \\x6f\x63\x00\x00\x0c\x00\x00\x00\x00\xa0\x00\x00\x00\x02\x00\x00\x00\x48\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x42\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x61\x00\x00\x00\x00\x00\x00\
+  \\x48\x00\x00\x00\x02\x00\x05\x00\x9c\x35\x00\x00\x4c\x2b\x00\x00\x01\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x30\x04\x00\xcc\x00\x00\x00\
+  \\x00\x00\x00\x00\x73\x09\x00\x00\x0a\x80\x05\x00\x00\x04\x17\x80\x06\x00\x00\x04\
+  \\x14\xfe\x06\x0d\x00\x00\x06\x73\x23\x00\x00\x06\x80\x07\x00\x00\x04\x73\x0a\x00\
+  \\x00\x0a\x80\x08\x00\x00\x04\x73\x0b\x00\x00\x0a\x80\x09\x00\x00\x04\x28\x0c\x00\
+  \\x00\x0a\x73\x0d\x00\x00\x0a\x6f\x0e\x00\x00\x0a\x26\x28\x0f\x00\x00\x0a\x28\x10\
+  \\x00\x00\x0a\x72\x01\x00\x00\x70\x73\x11\x00\x00\x0a\x19\x6f\x12\x00\x00\x0a\x80\
+  \\x01\x00\x00\x04\x7e\x01\x00\x00\x04\x72\x21\x00\x00\x70\x72\x3d\x00\x00\x70\x6f\
+  \\x13\x00\x00\x0a\x80\x02\x00\x00\x04\x7e\x02\x00\x00\x04\x72\x55\x00\x00\x70\x6f\
+  \\x14\x00\x00\x0a\x80\x03\x00\x00\x04\x7e\x05\x00\x00\x04\x7e\x06\x00\x00\x04\x25\
+  \\x17\x58\x80\x06\x00\x00\x04\x17\x8c\x24\x00\x00\x01\x6f\x15\x00\x00\x0a\x7e\x05\
+  \\x00\x00\x04\x7e\x06\x00\x00\x04\x25\x17\x58\x80\x06\x00\x00\x04\x16\x8c\x24\x00\
+  \\x00\x01\x6f\x15\x00\x00\x0a\x2a\x2e\x72\x61\x00\x00\x70\x28\x03\x00\x00\x06\x2a\
+  \\x13\x30\x03\x00\x2b\x00\x00\x00\x01\x00\x00\x11\xd0\x02\x00\x00\x02\x28\x16\x00\
+  \\x00\x0a\x02\x28\x17\x00\x00\x0a\x0a\x06\x2d\x10\x72\x87\x00\x00\x70\x72\xab\x00\
+  \\x00\x70\x73\x18\x00\x00\x0a\x7a\x06\x28\x12\x00\x00\x06\x2a\xbe\x02\x7e\x19\x00\
+  \\x00\x0a\x28\x1a\x00\x00\x0a\x2c\x07\x14\x80\x04\x00\x00\x04\x2a\x02\xd0\x05\x00\
+  \\x00\x02\x28\x16\x00\x00\x0a\x28\x1b\x00\x00\x0a\x74\x05\x00\x00\x02\x80\x04\x00\
+  \\x00\x04\x2a\x00\x13\x30\x02\x00\x37\x00\x00\x00\x02\x00\x00\x11\x7e\x03\x00\x00\
+  \\x04\x6f\x1c\x00\x00\x0a\x26\x7e\x02\x00\x00\x04\x6f\x1d\x00\x00\x0a\x28\x1e\x00\
+  \\x00\x0a\x0a\x72\xc1\x00\x00\x70\x06\x28\x1f\x00\x00\x0a\x28\x20\x00\x00\x0a\x7e\
+  \\x01\x00\x00\x04\x06\x6f\x21\x00\x00\x0a\x2a\x00\x13\x30\x03\x00\x40\x00\x00\x00\
+  \\x03\x00\x00\x11\x03\x72\xf5\x00\x00\x70\x28\x22\x00\x00\x0a\x2c\x19\x02\x28\x38\
+  \\x00\x00\x06\x04\x28\x39\x00\x00\x06\x6f\x23\x00\x00\x0a\x0a\x06\x28\x11\x00\x00\
+  \\x06\x2a\x02\x28\x38\x00\x00\x06\x03\x04\x28\x39\x00\x00\x06\x6f\x24\x00\x00\x0a\
+  \\x0b\x07\x28\x12\x00\x00\x06\x2a\x13\x30\x01\x00\x0e\x00\x00\x00\x04\x00\x00\x11\
+  \\x02\x28\x38\x00\x00\x06\x0a\x06\x28\x13\x00\x00\x06\x2a\x00\x00\x13\x30\x02\x00\
+  \\x14\x00\x00\x00\x05\x00\x00\x11\x02\x28\x38\x00\x00\x06\x03\x6f\x25\x00\x00\x0a\
+  \\x0a\x06\x28\x14\x00\x00\x06\x2a\x13\x30\x02\x00\x14\x00\x00\x00\x05\x00\x00\x11\
+  \\x02\x28\x38\x00\x00\x06\x03\x6f\x25\x00\x00\x0a\x0a\x06\x28\x15\x00\x00\x06\x2a\
+  \\x13\x30\x01\x00\x0e\x00\x00\x00\x04\x00\x00\x11\x02\x28\x38\x00\x00\x06\x0a\x06\
+  \\x28\x16\x00\x00\x06\x2a\x00\x00\x1b\x30\x03\x00\x50\x00\x00\x00\x06\x00\x00\x11\
+  \\x02\x2d\x02\x16\x2a\x02\x75\x04\x00\x00\x1b\x2c\x0e\x02\xa5\x24\x00\x00\x01\x0a\
+  \\x06\x2d\x02\x18\x2a\x17\x2a\x7e\x05\x00\x00\x04\x25\x0c\x28\x26\x00\x00\x0a\x7e\
+  \\x05\x00\x00\x04\x7e\x06\x00\x00\x04\x02\x6f\x15\x00\x00\x0a\x7e\x06\x00\x00\x04\
+  \\x25\x17\x58\x80\x06\x00\x00\x04\x0b\xde\x07\x08\x28\x27\x00\x00\x0a\xdc\x07\x2a\
+  \\x01\x10\x00\x00\x02\x00\x27\x00\x20\x47\x00\x07\x00\x00\x00\x00\x1b\x30\x03\x00\
+  \\x59\x00\x00\x00\x07\x00\x00\x11\x02\x2d\x02\x14\x2a\x02\x17\x33\x07\x17\x8c\x24\
+  \\x00\x00\x01\x2a\x02\x18\x33\x07\x16\x8c\x24\x00\x00\x01\x2a\x7e\x05\x00\x00\x04\
+  \\x25\x0c\x28\x26\x00\x00\x0a\x7e\x05\x00\x00\x04\x02\x12\x00\x6f\x28\x00\x00\x0a\
+  \\x2c\x04\x06\x0b\xde\x1d\x72\x01\x01\x00\x70\x02\x8c\x2e\x00\x00\x01\x28\x29\x00\
+  \\x00\x0a\x73\x2a\x00\x00\x0a\x7a\x08\x28\x27\x00\x00\x0a\xdc\x07\x2a\x00\x00\x00\
+  \\x01\x10\x00\x00\x02\x00\x27\x00\x29\x50\x00\x07\x00\x00\x00\x00\x1b\x30\x02\x00\
+  \\x22\x00\x00\x00\x08\x00\x00\x11\x7e\x05\x00\x00\x04\x25\x0a\x28\x26\x00\x00\x0a\
+  \\x7e\x05\x00\x00\x04\x02\x6f\x2b\x00\x00\x0a\x26\xde\x07\x06\x28\x27\x00\x00\x0a\
+  \\xdc\x2a\x00\x00\x01\x10\x00\x00\x02\x00\x0c\x00\x0e\x1a\x00\x07\x00\x00\x00\x00\
+  \\x1b\x30\x03\x00\x2a\x00\x00\x00\x09\x00\x00\x11\x02\x28\x2c\x00\x00\x0a\x0a\x7e\
+  \\x08\x00\x00\x04\x25\x0b\x28\x26\x00\x00\x0a\x7e\x08\x00\x00\x04\x06\x02\x6f\x2d\
+  \\x00\x00\x0a\xde\x07\x07\x28\x27\x00\x00\x0a\xdc\x06\x2a\x00\x00\x01\x10\x00\x00\
+  \\x02\x00\x13\x00\x0e\x21\x00\x07\x00\x00\x00\x00\x1b\x30\x02\x00\x22\x00\x00\x00\
+  \\x0a\x00\x00\x11\x7e\x08\x00\x00\x04\x25\x0a\x28\x26\x00\x00\x0a\x7e\x08\x00\x00\
+  \\x04\x02\x6f\x2e\x00\x00\x0a\x26\xde\x07\x06\x28\x27\x00\x00\x0a\xdc\x2a\x00\x00\
+  \\x01\x10\x00\x00\x02\x00\x0c\x00\x0e\x1a\x00\x07\x00\x00\x00\x00\x13\x30\x05\x00\
+  \\x65\x00\x00\x00\x0b\x00\x00\x11\x7e\x03\x00\x00\x04\x02\x1c\x0f\x01\x28\x27\x00\
+  \\x00\x06\x0f\x01\x28\x28\x00\x00\x06\x6f\x2f\x00\x00\x0a\x0a\x04\x06\x6f\x30\x00\
+  \\x00\x0a\x6f\x34\x00\x00\x06\x02\x0f\x01\x28\x27\x00\x00\x06\x0f\x01\x28\x28\x00\
+  \\x00\x06\xd0\x02\x00\x00\x02\x28\x16\x00\x00\x0a\x73\x31\x00\x00\x0a\x0b\x04\x07\
+  \\x6f\x32\x00\x00\x0a\x6f\x34\x00\x00\x06\x07\x0f\x01\x28\x2c\x00\x00\x06\x6f\x33\
+  \\x00\x00\x0a\x28\x0e\x00\x00\x06\x2a\x1e\x02\x28\x34\x00\x00\x0a\x2a\x00\x00\x00\
+  \\x03\x30\x03\x00\x7a\x00\x00\x00\x00\x00\x00\x00\x02\x7b\x1a\x00\x00\x04\x2d\x37\
+  \\x03\x02\x7b\x19\x00\x00\x04\x6f\x35\x00\x00\x0a\x26\x03\x7e\x36\x00\x00\x0a\x16\
+  \\x6f\x37\x00\x00\x0a\x03\x7e\x38\x00\x00\x0a\x02\x7b\x19\x00\x00\x04\x6f\x39\x00\
+  \\x00\x0a\x03\x7e\x3a\x00\x00\x0a\x6f\x3b\x00\x00\x0a\x2b\x23\x03\x16\x02\x7b\x1a\
+  \\x00\x00\x04\x6f\x3c\x00\x00\x0a\x28\x1d\x00\x00\x06\x03\x7e\x3d\x00\x00\x0a\x02\
+  \\x7b\x1a\x00\x00\x04\x6f\x3e\x00\x00\x0a\x03\x02\x7b\x19\x00\x00\x04\x28\x1e\x00\
+  \\x00\x06\x03\x7e\x3f\x00\x00\x0a\x6f\x3b\x00\x00\x0a\x2a\x00\x00\x13\x30\x05\x00\
+  \\x9b\x00\x00\x00\x0c\x00\x00\x11\x73\x45\x00\x00\x06\x0b\x07\x02\x7d\x1a\x00\x00\
+  \\x04\x07\x07\x7b\x1a\x00\x00\x04\x6f\x40\x00\x00\x0a\x7d\x19\x00\x00\x04\x07\x7b\
+  \\x19\x00\x00\x04\x6f\x41\x00\x00\x0a\x2d\x13\x07\x7b\x1a\x00\x00\x04\x2d\x0b\x72\
+  \\x37\x01\x00\x70\x73\x42\x00\x00\x0a\x7a\x12\x00\xd0\x2e\x00\x00\x01\x28\x16\x00\
+  \\x00\x0a\x07\x7b\x1a\x00\x00\x04\x2c\x17\x07\x7b\x1a\x00\x00\x04\x6f\x3c\x00\x00\
+  \\x0a\x28\x3d\x00\x00\x06\x28\x19\x00\x00\x06\x2b\x05\x7e\x43\x00\x00\x0a\x28\x29\
+  \\x00\x00\x06\x07\x7b\x19\x00\x00\x04\x6f\x44\x00\x00\x0a\x72\x9d\x01\x00\x70\x28\
+  \\x1f\x00\x00\x0a\x06\x07\xfe\x06\x46\x00\x00\x06\x73\x33\x00\x00\x06\x28\x10\x00\
+  \\x00\x06\x2a\x1e\x02\x28\x34\x00\x00\x0a\x2a\x00\x03\x30\x03\x00\x79\x00\x00\x00\
+  \\x00\x00\x00\x00\x02\x7b\x1b\x00\x00\x04\x6f\x45\x00\x00\x0a\x2c\x25\x03\x16\x02\
+  \\x7b\x1b\x00\x00\x04\x6f\x3c\x00\x00\x0a\x28\x1d\x00\x00\x06\x03\x7e\x46\x00\x00\
+  \\x0a\x02\x7b\x1b\x00\x00\x04\x6f\x47\x00\x00\x0a\x2b\x35\x03\x16\x02\x7b\x1b\x00\
+  \\x00\x04\x6f\x40\x00\x00\x0a\x28\x1b\x00\x00\x06\x03\x17\x02\x7b\x1b\x00\x00\x04\
+  \\x6f\x3c\x00\x00\x0a\x28\x1d\x00\x00\x06\x03\x7e\x48\x00\x00\x0a\x02\x7b\x1b\x00\
+  \\x00\x04\x6f\x47\x00\x00\x0a\x03\x02\x7b\x1b\x00\x00\x04\x6f\x49\x00\x00\x0a\x28\
+  \\x1f\x00\x00\x06\x2a\x00\x00\x00\x13\x30\x05\x00\xb1\x00\x00\x00\x0d\x00\x00\x11\
+  \\x73\x47\x00\x00\x06\x0c\x08\x02\x7d\x1b\x00\x00\x04\x08\x7b\x1b\x00\x00\x04\x6f\
+  \\x40\x00\x00\x0a\x0a\x12\x01\x08\x7b\x1b\x00\x00\x04\x6f\x49\x00\x00\x0a\x6f\x4a\
+  \\x00\x00\x0a\x28\x1a\x00\x00\x06\x08\x7b\x1b\x00\x00\x04\x6f\x45\x00\x00\x0a\x2d\
+  \\x2c\x08\x7b\x1b\x00\x00\x04\x6f\x40\x00\x00\x0a\x28\x1a\x00\x00\x06\x08\x7b\x1b\
+  \\x00\x00\x04\x6f\x3c\x00\x00\x0a\x28\x3d\x00\x00\x06\x28\x19\x00\x00\x06\x28\x01\
+  \\x00\x00\x2b\x2b\x15\x08\x7b\x1b\x00\x00\x04\x6f\x3c\x00\x00\x0a\x28\x3d\x00\x00\
+  \\x06\x28\x19\x00\x00\x06\x28\x29\x00\x00\x06\x06\x6f\x44\x00\x00\x0a\x72\xa5\x01\
+  \\x00\x70\x08\x7b\x1b\x00\x00\x04\x6f\x44\x00\x00\x0a\x28\x4b\x00\x00\x0a\x07\x08\
+  \\xfe\x06\x48\x00\x00\x06\x73\x33\x00\x00\x06\x28\x10\x00\x00\x06\x2a\x1e\x02\x28\
+  \\x34\x00\x00\x0a\x2a\x00\x00\x00\x13\x30\x06\x00\xa5\x00\x00\x00\x0e\x00\x00\x11\
+  \\x03\x7e\x4c\x00\x00\x0a\x6f\x3b\x00\x00\x0a\x03\x7e\x3d\x00\x00\x0a\x02\x7b\x1c\
+  \\x00\x00\x04\x17\x8d\x0b\x00\x00\x01\x0a\x06\x16\xd0\x27\x00\x00\x01\x28\x16\x00\
+  \\x00\x0a\xa2\x06\x6f\x23\x00\x00\x0a\x6f\x3e\x00\x00\x0a\x03\x7e\x4d\x00\x00\x0a\
+  \\x02\x7b\x1c\x00\x00\x04\x72\xa9\x01\x00\x70\x6f\x17\x00\x00\x0a\x6f\x47\x00\x00\
+  \\x0a\x03\x7e\x3d\x00\x00\x0a\x02\x7b\x1d\x00\x00\x04\x18\x8d\x0b\x00\x00\x01\x0b\
+  \\x07\x16\xd0\x01\x00\x00\x01\x28\x16\x00\x00\x0a\xa2\x07\x17\xd0\x27\x00\x00\x01\
+  \\x28\x16\x00\x00\x0a\xa2\x07\x6f\x23\x00\x00\x0a\x6f\x3e\x00\x00\x0a\x03\x7e\x46\
+  \\x00\x00\x0a\x7e\x14\x00\x00\x04\x6f\x47\x00\x00\x0a\x03\x7e\x3f\x00\x00\x0a\x6f\
+  \\x3b\x00\x00\x0a\x2a\x00\x00\x00\x13\x30\x05\x00\x78\x00\x00\x00\x0f\x00\x00\x11\
+  \\x73\x49\x00\x00\x06\x0b\x07\x02\x7d\x1d\x00\x00\x04\x07\x07\x7b\x1d\x00\x00\x04\
+  \\x28\x20\x00\x00\x06\x7d\x1c\x00\x00\x04\x07\x7b\x1d\x00\x00\x04\x28\x2b\x00\x00\
+  \\x06\x26\x12\x00\xd0\x2e\x00\x00\x01\x28\x16\x00\x00\x0a\x17\x8d\x0b\x00\x00\x01\
+  \\x0c\x08\x16\xd0\x27\x00\x00\x01\x28\x16\x00\x00\x0a\xa2\x08\x28\x29\x00\x00\x06\
+  \\x07\x7b\x1d\x00\x00\x04\x6f\x44\x00\x00\x0a\x72\x9d\x01\x00\x70\x28\x1f\x00\x00\
+  \\x0a\x06\x07\xfe\x06\x4a\x00\x00\x06\x73\x33\x00\x00\x06\x28\x10\x00\x00\x06\x2a\
+  \\x1e\x02\x28\x34\x00\x00\x0a\x2a\x13\x30\x03\x00\x94\x00\x00\x00\x10\x00\x00\x11\
+  \\x02\x7b\x1e\x00\x00\x04\x6f\x4e\x00\x00\x0a\x2c\x47\x02\x7b\x1e\x00\x00\x04\x6f\
+  \\x4f\x00\x00\x0a\x2c\x27\x02\x7b\x1e\x00\x00\x04\x6f\x50\x00\x00\x0a\x0a\x06\x75\
+  \\x2e\x00\x00\x01\x2c\x49\x03\x7e\x51\x00\x00\x0a\x06\xa5\x2e\x00\x00\x01\x6f\x52\
+  \\x00\x00\x0a\x2b\x36\x03\x7e\x53\x00\x00\x0a\x02\x7b\x1e\x00\x00\x04\x6f\x54\x00\
+  \\x00\x0a\x2b\x23\x03\x16\x02\x7b\x1e\x00\x00\x04\x6f\x40\x00\x00\x0a\x28\x1b\x00\
+  \\x00\x06\x03\x7e\x55\x00\x00\x0a\x02\x7b\x1e\x00\x00\x04\x6f\x54\x00\x00\x0a\x03\
+  \\x02\x7b\x1e\x00\x00\x04\x6f\x56\x00\x00\x0a\x28\x1e\x00\x00\x06\x03\x7e\x3f\x00\
+  \\x00\x0a\x6f\x3b\x00\x00\x0a\x2a\x13\x30\x05\x00\x8b\x00\x00\x00\x11\x00\x00\x11\
+  \\x73\x4b\x00\x00\x06\x0b\x07\x02\x7d\x1e\x00\x00\x04\x12\x00\x07\x7b\x1e\x00\x00\
+  \\x04\x6f\x56\x00\x00\x0a\x28\x1a\x00\x00\x06\x07\x7b\x1e\x00\x00\x04\x6f\x4e\x00\
+  \\x00\x0a\x2d\x1d\x17\x8d\x0b\x00\x00\x01\x0c\x08\x16\x07\x7b\x1e\x00\x00\x04\x6f\
+  \\x40\x00\x00\x0a\x28\x1a\x00\x00\x06\xa2\x08\x2b\x05\x7e\x43\x00\x00\x0a\x28\x29\
+  \\x00\x00\x06\x07\x7b\x1e\x00\x00\x04\x6f\x40\x00\x00\x0a\x6f\x44\x00\x00\x0a\x72\
+  \\xb7\x01\x00\x70\x07\x7b\x1e\x00\x00\x04\x6f\x44\x00\x00\x0a\x28\x4b\x00\x00\x0a\
+  \\x06\x07\xfe\x06\x4c\x00\x00\x06\x73\x33\x00\x00\x06\x28\x10\x00\x00\x06\x2a\x1e\
+  \\x02\x28\x34\x00\x00\x0a\x2a\x00\x03\x30\x03\x00\x73\x00\x00\x00\x00\x00\x00\x00\
+  \\x02\x7b\x1f\x00\x00\x04\x6f\x4e\x00\x00\x0a\x2c\x25\x03\x16\x02\x7b\x1f\x00\x00\
+  \\x04\x6f\x56\x00\x00\x0a\x28\x1b\x00\x00\x06\x03\x7e\x57\x00\x00\x0a\x02\x7b\x1f\
+  \\x00\x00\x04\x6f\x54\x00\x00\x0a\x2b\x35\x03\x16\x02\x7b\x1f\x00\x00\x04\x6f\x40\
+  \\x00\x00\x0a\x28\x1b\x00\x00\x06\x03\x17\x02\x7b\x1f\x00\x00\x04\x6f\x56\x00\x00\
+  \\x0a\x28\x1b\x00\x00\x06\x03\x7e\x58\x00\x00\x0a\x02\x7b\x1f\x00\x00\x04\x6f\x54\
+  \\x00\x00\x0a\x03\x7e\x3f\x00\x00\x0a\x6f\x3b\x00\x00\x0a\x2a\x00\x13\x30\x06\x00\
+  \\xae\x00\x00\x00\x12\x00\x00\x11\x73\x4d\x00\x00\x06\x0b\x07\x02\x7d\x1f\x00\x00\
+  \\x04\x12\x00\xd0\x38\x00\x00\x01\x28\x16\x00\x00\x0a\x07\x7b\x1f\x00\x00\x04\x6f\
+  \\x4e\x00\x00\x0a\x2d\x30\x18\x8d\x0b\x00\x00\x01\x0c\x08\x16\x07\x7b\x1f\x00\x00\
+  \\x04\x6f\x40\x00\x00\x0a\x28\x1a\x00\x00\x06\xa2\x08\x17\x07\x7b\x1f\x00\x00\x04\
+  \\x6f\x56\x00\x00\x0a\x28\x1a\x00\x00\x06\xa2\x08\x2b\x1b\x17\x8d\x0b\x00\x00\x01\
+  \\x0d\x09\x16\x07\x7b\x1f\x00\x00\x04\x6f\x56\x00\x00\x0a\x28\x1a\x00\x00\x06\xa2\
+  \\x09\x28\x29\x00\x00\x06\x07\x7b\x1f\x00\x00\x04\x6f\x40\x00\x00\x0a\x6f\x44\x00\
+  \\x00\x0a\x72\xcf\x01\x00\x70\x07\x7b\x1f\x00\x00\x04\x6f\x44\x00\x00\x0a\x28\x4b\
+  \\x00\x00\x0a\x06\x07\xfe\x06\x4e\x00\x00\x06\x73\x33\x00\x00\x06\x28\x10\x00\x00\
+  \\x06\x2a\x1e\x02\x28\x34\x00\x00\x0a\x2a\x00\x00\x03\x30\x03\x00\x47\x00\x00\x00\
+  \\x00\x00\x00\x00\x03\x16\x02\x7b\x20\x00\x00\x04\x28\x1b\x00\x00\x06\x02\x7b\x20\
+  \\x00\x00\x04\x6f\x41\x00\x00\x0a\x2c\x11\x03\x7e\x59\x00\x00\x0a\x02\x7b\x20\x00\
+  \\x00\x04\x6f\x39\x00\x00\x0a\x03\xd0\x01\x00\x00\x01\x28\x16\x00\x00\x0a\x28\x1e\
+  \\x00\x00\x06\x03\x7e\x3f\x00\x00\x0a\x6f\x3b\x00\x00\x0a\x2a\x00\x13\x30\x05\x00\
+  \\x5c\x00\x00\x00\x13\x00\x00\x11\x73\x4f\x00\x00\x06\x0b\x07\x02\x7d\x20\x00\x00\
+  \\x04\x12\x00\xd0\x2e\x00\x00\x01\x28\x16\x00\x00\x0a\x17\x8d\x0b\x00\x00\x01\x0c\
+  \\x08\x16\x07\x7b\x20\x00\x00\x04\x28\x1a\x00\x00\x06\xa2\x08\x28\x29\x00\x00\x06\
+  \\x72\xe7\x01\x00\x70\x07\x7b\x20\x00\x00\x04\x6f\x44\x00\x00\x0a\x28\x1f\x00\x00\
+  \\x0a\x06\x07\xfe\x06\x50\x00\x00\x06\x73\x33\x00\x00\x06\x28\x10\x00\x00\x06\x2a\
+  \\xa2\x02\x6f\x5a\x00\x00\x0a\x2d\x1e\x02\xd0\x38\x00\x00\x01\x28\x16\x00\x00\x0a\
+  \\x2e\x11\x02\xd0\x2b\x00\x00\x01\x28\x16\x00\x00\x0a\xfe\x01\x16\xfe\x01\x2a\x16\
+  \\x2a\x00\x00\x00\x13\x30\x02\x00\x1f\x00\x00\x00\x14\x00\x00\x11\x02\xd0\x2b\x00\
+  \\x00\x01\x28\x16\x00\x00\x0a\x33\x08\x1f\x15\x73\x5b\x00\x00\x0a\x2a\x12\x00\xfe\
+  \\x15\x05\x00\x00\x1b\x06\x2a\x4e\x14\xfe\x06\x1a\x00\x00\x06\x73\x5c\x00\x00\x0a\
+  \\x02\x28\x02\x00\x00\x2b\x2a\x56\x02\x28\x17\x00\x00\x06\x2c\x0b\xd0\x2e\x00\x00\
+  \\x01\x28\x16\x00\x00\x0a\x2a\x02\x2a\x3e\x02\x03\x28\x3e\x00\x00\x06\x02\x04\x28\
+  \\x1c\x00\x00\x06\x2a\x96\x03\x28\x17\x00\x00\x06\x2c\x1c\x02\x7e\x46\x00\x00\x0a\
+  \\x7e\x15\x00\x00\x04\x6f\x47\x00\x00\x0a\x02\x7e\x5d\x00\x00\x0a\x03\x6f\x39\x00\
+  \\x00\x0a\x2a\x00\x1b\x30\x04\x00\x40\x00\x00\x00\x15\x00\x00\x11\x03\x0a\x04\x6f\
+  \\x5e\x00\x00\x0a\x0d\x2b\x20\x09\x6f\x5f\x00\x00\x0a\x0b\x07\x6f\x4a\x00\x00\x0a\
+  \\x0c\x02\x06\x25\x17\x58\x0a\x28\x3e\x00\x00\x06\x02\x08\x28\x1c\x00\x00\x06\x09\
+  \\x6f\x60\x00\x00\x0a\x2d\xd8\xde\x0a\x09\x2c\x06\x09\x6f\x61\x00\x00\x0a\xdc\x2a\
+  \\x01\x10\x00\x00\x02\x00\x09\x00\x2c\x35\x00\x0a\x00\x00\x00\x00\xb6\x03\x28\x17\
+  \\x00\x00\x06\x2c\x24\x03\x6f\x41\x00\x00\x0a\x2c\x0c\x02\x7e\x59\x00\x00\x0a\x03\
+  \\x6f\x39\x00\x00\x0a\x02\x7e\x46\x00\x00\x0a\x7e\x14\x00\x00\x04\x6f\x47\x00\x00\
+  \\x0a\x2a\x00\x00\x13\x30\x02\x00\x1a\x00\x00\x00\x04\x00\x00\x11\x03\x6f\x4a\x00\
+  \\x00\x0a\x0a\x02\x06\x28\x1e\x00\x00\x06\x02\x7e\x3f\x00\x00\x0a\x6f\x3b\x00\x00\
+  \\x0a\x2a\x00\x00\x1b\x30\x03\x00\x4d\x00\x00\x00\x16\x00\x00\x11\x02\x6f\x44\x00\
+  \\x00\x0a\x72\xf1\x01\x00\x70\x28\x1f\x00\x00\x0a\x0a\x7e\x09\x00\x00\x04\x25\x0d\
+  \\x28\x26\x00\x00\x0a\x7e\x09\x00\x00\x04\x06\x12\x01\x6f\x62\x00\x00\x0a\x2d\x14\
+  \\x06\x02\x28\x21\x00\x00\x06\x0b\x7e\x09\x00\x00\x04\x06\x07\x6f\x63\x00\x00\x0a\
+  \\x07\x0c\xde\x07\x09\x28\x27\x00\x00\x0a\xdc\x08\x2a\x00\x00\x00\x01\x10\x00\x00\
+  \\x02\x00\x1d\x00\x27\x44\x00\x07\x00\x00\x00\x00\x13\x30\x06\x00\x68\x02\x00\x00\
+  \\x17\x00\x00\x11\x03\x28\x2b\x00\x00\x06\x0a\x12\x00\x28\x27\x00\x00\x06\x28\x1a\
+  \\x00\x00\x06\x12\x00\x28\x28\x00\x00\x06\x28\x19\x00\x00\x06\x73\x29\x00\x00\x06\
+  \\x13\x0c\x12\x0c\x28\x2c\x00\x00\x06\x0b\x7e\x02\x00\x00\x04\x02\x20\x01\x01\x00\
+  \\x00\x6f\x64\x00\x00\x0a\x0c\x08\x72\x01\x02\x00\x70\x07\x17\x6f\x65\x00\x00\x0a\
+  \\x0d\x08\x20\x06\x10\x00\x00\x17\x17\x8d\x0b\x00\x00\x01\x13\x0d\x11\x0d\x16\xd0\
+  \\x27\x00\x00\x01\x28\x16\x00\x00\x0a\xa2\x11\x0d\x6f\x66\x00\x00\x0a\x13\x04\x11\
+  \\x04\x6f\x67\x00\x00\x0a\x13\x05\x11\x05\x7e\x4c\x00\x00\x0a\x6f\x3b\x00\x00\x0a\
+  \\x11\x05\x7e\x46\x00\x00\x0a\x7e\x0e\x00\x00\x04\x6f\x3e\x00\x00\x0a\x11\x05\x7e\
+  \\x4c\x00\x00\x0a\x6f\x3b\x00\x00\x0a\x11\x05\x7e\x68\x00\x00\x0a\x6f\x3b\x00\x00\
+  \\x0a\x11\x05\x7e\x69\x00\x00\x0a\x07\x6f\x39\x00\x00\x0a\x11\x05\x7e\x46\x00\x00\
+  \\x0a\x7e\x0d\x00\x00\x04\x6f\x47\x00\x00\x0a\x11\x05\x7e\x46\x00\x00\x0a\x7e\x0f\
+  \\x00\x00\x04\x6f\x47\x00\x00\x0a\x11\x05\x7e\x6a\x00\x00\x0a\x07\x6f\x39\x00\x00\
+  \\x0a\x11\x05\x7e\x58\x00\x00\x0a\x09\x6f\x54\x00\x00\x0a\x11\x05\x7e\x3f\x00\x00\
+  \\x0a\x6f\x3b\x00\x00\x0a\x08\x72\x1f\x02\x00\x70\x20\xc4\x00\x00\x00\x6f\x6b\x00\
+  \\x00\x0a\x13\x06\x11\x06\x16\x6f\x6c\x00\x00\x0a\x11\x06\x6f\x30\x00\x00\x0a\x13\
+  \\x07\x11\x07\x6f\x6d\x00\x00\x0a\x13\x08\x11\x07\x7e\x53\x00\x00\x0a\x7e\x13\x00\
+  \\x00\x04\x6f\x54\x00\x00\x0a\x11\x07\x7e\x6e\x00\x00\x0a\x6f\x3b\x00\x00\x0a\x11\
+  \\x07\x7e\x6f\x00\x00\x0a\x11\x08\x6f\x70\x00\x00\x0a\x11\x07\x7e\x53\x00\x00\x0a\
+  \\x7e\x13\x00\x00\x04\x6f\x54\x00\x00\x0a\x11\x07\x7e\x4c\x00\x00\x0a\x6f\x3b\x00\
+  \\x00\x0a\x11\x07\x7e\x55\x00\x00\x0a\x09\x6f\x54\x00\x00\x0a\x11\x07\x7e\x46\x00\
+  \\x00\x0a\x7e\x10\x00\x00\x04\x6f\x47\x00\x00\x0a\x11\x07\x7e\x46\x00\x00\x0a\x7e\
+  \\x16\x00\x00\x04\x6f\x47\x00\x00\x0a\x11\x07\x11\x08\x6f\x71\x00\x00\x0a\x11\x07\
+  \\x7e\x3f\x00\x00\x0a\x6f\x3b\x00\x00\x0a\x08\x72\xa9\x01\x00\x70\x1c\x12\x00\x28\
+  \\x27\x00\x00\x06\x12\x00\x28\x28\x00\x00\x06\x6f\x2f\x00\x00\x0a\x13\x09\x11\x09\
+  \\x6f\x30\x00\x00\x0a\x13\x0a\x11\x0a\x7e\x4c\x00\x00\x0a\x6f\x3b\x00\x00\x0a\x11\
+  \\x0a\x7e\x55\x00\x00\x0a\x09\x6f\x54\x00\x00\x0a\x16\x13\x0b\x2b\x22\x11\x0a\x11\
+  \\x0b\x17\x58\x28\x3e\x00\x00\x06\x11\x0a\x12\x00\x28\x28\x00\x00\x06\x11\x0b\x9a\
+  \\x28\x1e\x00\x00\x06\x11\x0b\x17\x58\x13\x0b\x11\x0b\x12\x00\x28\x28\x00\x00\x06\
+  \\x8e\x69\x32\xd1\x11\x0a\x7e\x48\x00\x00\x0a\x07\x72\xa9\x01\x00\x70\x6f\x17\x00\
+  \\x00\x0a\x6f\x47\x00\x00\x0a\x11\x0a\x12\x00\x28\x27\x00\x00\x06\x28\x1c\x00\x00\
+  \\x06\x11\x0a\x7e\x3f\x00\x00\x0a\x6f\x3b\x00\x00\x0a\x08\x6f\x1c\x00\x00\x0a\x2a\
+  \\x1e\x02\x28\x34\x00\x00\x0a\x2a\x1e\x02\x7b\x0a\x00\x00\x04\x2a\x1e\x02\x7b\x0b\
+  \\x00\x00\x04\x2a\x3e\x02\x03\x7d\x0a\x00\x00\x04\x02\x04\x7d\x0b\x00\x00\x04\x2a\
+  \\x13\x30\x02\x00\x51\x00\x00\x00\x18\x00\x00\x11\x73\x74\x00\x00\x0a\x0a\x02\x7b\
+  \\x0b\x00\x00\x04\x0c\x16\x0d\x2b\x21\x08\x09\x9a\x0b\x06\x07\x6f\x44\x00\x00\x0a\
+  \\x6f\x75\x00\x00\x0a\x26\x06\x72\x31\x02\x00\x70\x6f\x75\x00\x00\x0a\x26\x09\x17\
+  \\x58\x0d\x09\x08\x8e\x69\x32\xd9\x06\x02\x7b\x0a\x00\x00\x04\x6f\x44\x00\x00\x0a\
+  \\x6f\x75\x00\x00\x0a\x26\x06\x6f\x76\x00\x00\x0a\x2a\x00\x00\x00\x13\x30\x03\x00\
+  \\x23\x00\x00\x00\x01\x00\x00\x11\x02\x72\xa9\x01\x00\x70\x6f\x17\x00\x00\x0a\x0a\
+  \\x06\x6f\x77\x00\x00\x0a\x06\x6f\x3c\x00\x00\x0a\x28\x3d\x00\x00\x06\x73\x29\x00\
+  \\x00\x06\x2a\x00\x1b\x30\x03\x00\x53\x00\x00\x00\x16\x00\x00\x11\x02\xfe\x16\x04\
+  \\x00\x00\x02\x6f\x76\x00\x00\x0a\x72\x37\x02\x00\x70\x28\x1f\x00\x00\x0a\x0a\x7e\
+  \\x0c\x00\x00\x04\x25\x0d\x28\x26\x00\x00\x0a\x7e\x0c\x00\x00\x04\x06\x12\x01\x6f\
+  \\x62\x00\x00\x0a\x2d\x14\x02\x06\x28\x2d\x00\x00\x06\x0b\x7e\x0c\x00\x00\x04\x06\
+  \\x07\x6f\x63\x00\x00\x0a\x07\x0c\xde\x07\x09\x28\x27\x00\x00\x0a\xdc\x08\x2a\x00\
+  \\x01\x10\x00\x00\x02\x00\x23\x00\x27\x4a\x00\x07\x00\x00\x00\x00\x13\x30\x06\x00\
+  \\x65\x01\x00\x00\x19\x00\x00\x11\x7e\x02\x00\x00\x04\x03\x20\x01\x01\x02\x00\xd0\
+  \\x02\x00\x00\x01\x28\x16\x00\x00\x0a\x6f\x78\x00\x00\x0a\x0a\x06\xd0\x43\x00\x00\
+  \\x01\x28\x16\x00\x00\x0a\x17\x8d\x0b\x00\x00\x01\x13\x06\x11\x06\x16\xd0\x44\x00\
+  \\x00\x01\x28\x16\x00\x00\x0a\xa2\x11\x06\x28\x23\x00\x00\x0a\x17\x8d\x01\x00\x00\
+  \\x01\x13\x07\x11\x07\x16\x19\x8c\x44\x00\x00\x01\xa2\x11\x07\x73\x79\x00\x00\x0a\
+  \\x6f\x7a\x00\x00\x0a\x06\x20\x86\x10\x00\x00\x17\x18\x8d\x0b\x00\x00\x01\x13\x08\
+  \\x11\x08\x16\xd0\x01\x00\x00\x01\x28\x16\x00\x00\x0a\xa2\x11\x08\x17\xd0\x27\x00\
+  \\x00\x01\x28\x16\x00\x00\x0a\xa2\x11\x08\x6f\x66\x00\x00\x0a\x0b\x07\x19\x6f\x7b\
+  \\x00\x00\x0a\x06\x72\xa9\x01\x00\x70\x20\xc6\x01\x00\x00\x02\x28\x27\x00\x00\x06\
+  \\x02\x28\x28\x00\x00\x06\x6f\x2f\x00\x00\x0a\x0c\x08\x19\x6f\x6c\x00\x00\x0a\x16\
+  \\x0d\x38\x88\x00\x00\x00\x09\x2d\x0f\x02\x28\x27\x00\x00\x06\x28\x18\x00\x00\x06\
+  \\x13\x04\x2b\x11\x02\x28\x28\x00\x00\x06\x09\x17\x59\x9a\x28\x18\x00\x00\x06\x13\
+  \\x04\x12\x04\x28\x7c\x00\x00\x0a\x2c\x58\x08\x09\x16\x14\x6f\x7d\x00\x00\x0a\x13\
+  \\x05\x11\x05\xd0\x4b\x00\x00\x01\x28\x16\x00\x00\x0a\x17\x8d\x0b\x00\x00\x01\x13\
+  \\x09\x11\x09\x16\xd0\x0e\x00\x00\x01\x28\x16\x00\x00\x0a\xa2\x11\x09\x28\x23\x00\
+  \\x00\x0a\x17\x8d\x01\x00\x00\x01\x13\x0a\x11\x0a\x16\x12\x04\x28\x7e\x00\x00\x0a\
+  \\x8c\x0e\x00\x00\x01\xa2\x11\x0a\x73\x79\x00\x00\x0a\x6f\x7f\x00\x00\x0a\x09\x17\
+  \\x58\x0d\x09\x02\x28\x28\x00\x00\x06\x8e\x69\x17\x58\x3f\x68\xff\xff\xff\x06\x6f\
+  \\x1c\x00\x00\x0a\x2a\x2e\x73\x0b\x00\x00\x0a\x80\x0c\x00\x00\x04\x2a\x00\x00\x00\
+  \\x03\x30\x03\x00\x01\x01\x00\x00\x00\x00\x00\x00\xd0\x0b\x00\x00\x01\x28\x16\x00\
+  \\x00\x0a\x72\x49\x02\x00\x70\x28\x17\x00\x00\x0a\x80\x0d\x00\x00\x04\xd0\x01\x00\
+  \\x00\x01\x28\x16\x00\x00\x0a\x7e\x43\x00\x00\x0a\x28\x23\x00\x00\x0a\x80\x0e\x00\
+  \\x00\x04\xd0\x28\x00\x00\x01\x28\x16\x00\x00\x0a\x72\x6d\x02\x00\x70\x28\x17\x00\
+  \\x00\x0a\x80\x0f\x00\x00\x04\xd0\x28\x00\x00\x01\x28\x16\x00\x00\x0a\x72\xa9\x02\
+  \\x00\x70\x28\x17\x00\x00\x0a\x80\x10\x00\x00\x04\xd0\x28\x00\x00\x01\x28\x16\x00\
+  \\x00\x0a\x72\xe5\x02\x00\x70\x28\x17\x00\x00\x0a\x80\x11\x00\x00\x04\xd0\x28\x00\
+  \\x00\x01\x28\x16\x00\x00\x0a\x72\x0b\x03\x00\x70\x28\x17\x00\x00\x0a\x80\x12\x00\
+  \\x00\x04\xd0\x02\x00\x00\x02\x28\x16\x00\x00\x0a\x72\x33\x03\x00\x70\x1f\x18\x6f\
+  \\x81\x00\x00\x0a\x80\x13\x00\x00\x04\xd0\x02\x00\x00\x02\x28\x16\x00\x00\x0a\x72\
+  \\x57\x03\x00\x70\x1f\x18\x28\x82\x00\x00\x0a\x80\x14\x00\x00\x04\xd0\x02\x00\x00\
+  \\x02\x28\x16\x00\x00\x0a\x72\x75\x03\x00\x70\x1f\x18\x28\x82\x00\x00\x0a\x80\x15\
+  \\x00\x00\x04\xd0\x05\x00\x00\x02\x28\x16\x00\x00\x0a\x72\xa9\x01\x00\x70\x28\x17\
+  \\x00\x00\x0a\x80\x16\x00\x00\x04\x2a\x22\x02\x17\x28\x83\x00\x00\x0a\x2a\x1e\x02\
+  \\x28\x38\x00\x00\x06\x2a\x00\x00\x13\x30\x05\x00\x37\x00\x00\x00\x1a\x00\x00\x11\
+  \\x7e\x17\x00\x00\x04\x2d\x11\x14\xfe\x06\x3f\x00\x00\x06\x73\x84\x00\x00\x0a\x80\
+  \\x17\x00\x00\x04\x7e\x17\x00\x00\x04\x02\x17\x8d\x4e\x00\x00\x01\x0a\x06\x16\x1f\
+  \\x3b\x9d\x06\x17\x6f\x85\x00\x00\x0a\x28\x03\x00\x00\x2b\x2a\x00\x13\x30\x04\x00\
+  \\x4b\x00\x00\x00\x1b\x00\x00\x11\x02\x8e\x69\x03\x8e\x69\x58\x8d\x0a\x00\x00\x1b\
+  \\x0a\x16\x0b\x2b\x12\x06\x07\x02\x07\xa3\x0a\x00\x00\x1b\xa4\x0a\x00\x00\x1b\x07\
+  \\x17\x58\x0b\x07\x02\x8e\x69\x32\xe8\x16\x0c\x2b\x16\x06\x02\x8e\x69\x08\x58\x03\
+  \\x08\xa3\x0a\x00\x00\x1b\xa4\x0a\x00\x00\x1b\x08\x17\x58\x0c\x08\x03\x8e\x69\x32\
+  \\xe4\x06\x2a\x00\x13\x30\x04\x00\x33\x00\x00\x00\x1c\x00\x00\x11\x17\x03\x8e\x69\
+  \\x58\x8d\x0a\x00\x00\x1b\x0a\x06\x16\x02\xa4\x0a\x00\x00\x1b\x16\x0b\x2b\x14\x06\
+  \\x17\x07\x58\x03\x07\xa3\x0a\x00\x00\x1b\xa4\x0a\x00\x00\x1b\x07\x17\x58\x0b\x07\
+  \\x03\x8e\x69\x32\xe6\x06\x2a\x00\x13\x30\x05\x00\x2d\x00\x00\x00\x1d\x00\x00\x11\
+  \\x03\x8e\x69\x8d\x0b\x00\x00\x1b\x0a\x16\x0b\x2b\x18\x06\x07\x02\x03\x07\xa3\x0a\
+  \\x00\x00\x1b\x6f\x86\x00\x00\x0a\xa4\x0b\x00\x00\x1b\x07\x17\x58\x0b\x07\x03\x8e\
+  \\x69\x32\xe2\x06\x2a\x1e\x02\x6f\x4a\x00\x00\x0a\x2a\x92\x7e\x18\x00\x00\x04\x2d\
+  \\x11\x14\xfe\x06\x40\x00\x00\x06\x73\x87\x00\x00\x0a\x80\x18\x00\x00\x04\x7e\x18\
+  \\x00\x00\x04\x02\x28\x04\x00\x00\x2b\x2a\x00\x00\x03\x30\x03\x00\x62\x00\x00\x00\
+  \\x00\x00\x00\x00\x03\x2d\x0c\x02\x7e\x4c\x00\x00\x0a\x6f\x3b\x00\x00\x0a\x2a\x03\
+  \\x17\x33\x0c\x02\x7e\x68\x00\x00\x0a\x6f\x3b\x00\x00\x0a\x2a\x03\x18\x33\x0c\x02\
+  \\x7e\x88\x00\x00\x0a\x6f\x3b\x00\x00\x0a\x2a\x03\x19\x33\x0c\x02\x7e\x89\x00\x00\
+  \\x0a\x6f\x3b\x00\x00\x0a\x2a\x03\x20\xff\x00\x00\x00\x30\x0e\x02\x7e\x8a\x00\x00\
+  \\x0a\x03\xd2\x6f\x37\x00\x00\x0a\x2a\x02\x7e\x8b\x00\x00\x0a\x03\x6f\x52\x00\x00\
+  \\x0a\x2a\x00\x00\x42\x53\x4a\x42\x01\x00\x01\x00\x00\x00\x00\x00\x0c\x00\x00\x00\
+  \\x76\x32\x2e\x30\x2e\x35\x30\x37\x32\x37\x00\x00\x00\x00\x05\x00\x6c\x00\x00\x00\
+  \\x4c\x0f\x00\x00\x23\x7e\x00\x00\xb8\x0f\x00\x00\xf4\x11\x00\x00\x23\x53\x74\x72\
+  \\x69\x6e\x67\x73\x00\x00\x00\x00\xac\x21\x00\x00\x8c\x03\x00\x00\x23\x55\x53\x00\
+  \\x38\x25\x00\x00\x10\x00\x00\x00\x23\x47\x55\x49\x44\x00\x00\x00\x48\x25\x00\x00\
+  \\x04\x06\x00\x00\x23\x42\x6c\x6f\x62\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\
+  \\x57\x15\xa2\x09\x09\x0e\x00\x00\x00\xfa\x01\x33\x00\x16\x00\x00\x01\x00\x00\x00\
+  \\x4f\x00\x00\x00\x0f\x00\x00\x00\x20\x00\x00\x00\x50\x00\x00\x00\x5f\x00\x00\x00\
+  \\x8b\x00\x00\x00\x13\x00\x00\x00\x1d\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\
+  \\x02\x00\x00\x00\x0d\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\x09\x00\x00\x00\
+  \\x06\x00\x00\x00\x04\x00\x00\x00\x00\x00\x0a\x00\x01\x00\x00\x00\x00\x00\x06\x00\
+  \\x9c\x00\x95\x00\x06\x00\xa3\x00\x95\x00\x06\x00\xb5\x00\x95\x00\x06\x00\xda\x00\
+  \\xc3\x00\x06\x00\xfb\x00\xc3\x00\x06\x00\x1f\x01\xc3\x00\x06\x00\x06\x02\xeb\x01\
+  \\x06\x00\x62\x02\x95\x00\x06\x00\xd6\x02\xc4\x02\x06\x00\xfe\x02\xc4\x02\x06\x00\
+  \\x1c\x03\x95\x00\x06\x00\x41\x03\xc4\x02\x06\x00\x98\x03\x95\x00\x06\x00\xc2\x03\
+  \\xa3\x03\x06\x00\x03\x04\xc3\x00\x06\x00\x31\x04\xeb\x01\x06\x00\x3f\x04\xc4\x02\
+  \\x06\x00\xc0\x04\x95\x00\x06\x00\xcd\x04\x95\x00\x06\x00\xec\x06\xc4\x02\x06\x00\
+  \\x09\x07\xc4\x02\x06\x00\x22\x07\xc4\x02\x06\x00\x3d\x07\xc4\x02\x06\x00\x56\x07\
+  \\xc4\x02\x06\x00\x73\x07\xc4\x02\x06\x00\xaa\x07\x8a\x07\x06\x00\xca\x07\x8a\x07\
+  \\x0a\x00\xfb\x07\xe8\x07\x0a\x00\x01\x08\xe8\x07\x0a\x00\x27\x08\xe8\x07\x0a\x00\
+  \\x3c\x08\xe8\x07\x0e\x00\x63\x08\x4e\x08\x06\x00\x82\x08\x95\x00\x06\x00\x9e\x08\
+  \\xc4\x02\x06\x00\xab\x08\xc3\x00\x06\x00\xf6\x08\x95\x00\x06\x00\x09\x09\x95\x00\
+  \\x06\x00\x37\x09\x95\x00\x06\x00\x5b\x09\x95\x00\x06\x00\x73\x09\xa3\x03\x06\x00\
+  \\xa4\x09\xc4\x02\x06\x00\xcc\x09\xc2\x09\x06\x00\xdd\x09\x95\x00\x06\x00\xeb\x09\
+  \\x95\x00\x06\x00\x6e\x0a\x5d\x0a\x06\x00\x91\x0a\x95\x00\x06\x00\xde\x0a\xc3\x00\
+  \\x06\x00\xec\x0a\xc4\x02\x06\x00\x19\x0b\xc3\x00\x06\x00\x74\x0b\xc3\x00\x06\x00\
+  \\x8e\x0b\xc3\x00\x06\x00\x96\x0b\xc3\x00\x06\x00\xbb\x0b\xc4\x02\x06\x00\xdf\x0b\
+  \\xc4\x02\x06\x00\x0c\x0c\x95\x00\x06\x00\xbb\x0d\x95\x00\x06\x00\x60\x0e\xeb\x01\
+  \\x06\x00\x9b\x0e\x88\x0e\x06\x00\xb0\x0e\x95\x00\x06\x00\xdd\x0e\xc4\x02\x06\x00\
+  \\xec\x0e\xc3\x00\x06\x00\xf9\x0e\xc4\x02\x06\x00\x15\x0f\xc3\x00\x06\x00\x28\x0f\
+  \\xc4\x02\x06\x00\x67\x0f\xc4\x02\x06\x00\x93\x0f\xc3\x00\x06\x00\xbc\x0f\xa3\x03\
+  \\x06\x00\xde\x0f\xa3\x03\x06\x00\x0e\x10\xa3\x03\x06\x00\x24\x10\xa3\x03\x06\x00\
+  \\x55\x10\x49\x10\x06\x00\x6a\x10\xc3\x00\x06\x00\xa1\x10\xc3\x00\x06\x00\xb2\x10\
+  \\xc4\x02\x06\x00\xd6\x10\xa3\x03\x06\x00\xf3\x10\x8a\x07\x06\x00\x0e\x11\xc4\x02\
+  \\x06\x00\x5d\x11\x95\x00\x06\x00\x62\x11\x95\x00\x00\x00\x00\x00\x01\x00\x00\x00\
+  \\x00\x00\x01\x00\x01\x00\x01\x00\x00\x00\x14\x00\x1b\x00\x05\x00\x01\x00\x01\x00\
+  \\x02\x01\x00\x00\x21\x00\x00\x00\x09\x00\x0a\x00\x23\x00\x0a\x01\x10\x00\x37\x00\
+  \\x00\x00\x0d\x00\x0a\x00\x27\x00\x01\x01\x00\x00\x49\x00\x1b\x00\x09\x00\x0d\x00\
+  \\x2f\x00\x01\x01\x00\x00\x63\x00\x1b\x00\x09\x00\x0d\x00\x33\x00\x80\x01\x10\x00\
+  \\x74\x00\x1b\x00\x05\x00\x0d\x00\x37\x00\x80\x01\x10\x00\x80\x00\x1b\x00\x05\x00\
+  \\x17\x00\x38\x00\x02\x01\x00\x00\x85\x00\x00\x00\x09\x00\x19\x00\x41\x00\x03\x01\
+  \\x10\x00\x36\x0b\x00\x00\x05\x00\x19\x00\x45\x00\x03\x01\x10\x00\x36\x0c\x00\x00\
+  \\x05\x00\x1b\x00\x47\x00\x03\x01\x10\x00\xa8\x0c\x00\x00\x05\x00\x1c\x00\x49\x00\
+  \\x03\x01\x10\x00\x08\x0d\x00\x00\x05\x00\x1e\x00\x4b\x00\x03\x01\x10\x00\x80\x0d\
+  \\x00\x00\x05\x00\x1f\x00\x4d\x00\x03\x01\x10\x00\xc0\x0d\x00\x00\x05\x00\x20\x00\
+  \\x4f\x00\x13\x00\xea\x00\x0a\x00\x13\x00\x09\x01\x0e\x00\x13\x00\x2b\x01\x12\x00\
+  \\x16\x00\x71\x01\x28\x00\x11\x00\x13\x02\x39\x00\x11\x00\x1c\x02\x41\x00\x11\x00\
+  \\x3d\x02\x4e\x00\x11\x00\x6b\x02\x57\x00\x11\x00\x6c\x04\xce\x00\x01\x00\xf1\x04\
+  \\xfd\x00\x01\x00\xfd\x04\x01\x01\x11\x00\x49\x05\xce\x00\x36\x00\x94\x05\x54\x01\
+  \\x36\x00\xab\x05\x58\x01\x36\x00\xb7\x05\x54\x01\x36\x00\xdd\x05\x54\x01\x36\x00\
+  \\x03\x06\x54\x01\x36\x00\x1e\x06\x54\x01\x36\x00\x3a\x06\x5c\x01\x36\x00\x53\x06\
+  \\x54\x01\x36\x00\x69\x06\x54\x01\x36\x00\x7a\x06\x54\x01\x11\x00\x39\x11\x0d\x05\
+  \\x11\x00\xa1\x11\x5f\x05\x06\x00\x49\x0b\xfd\x00\x06\x00\x4e\x0b\x58\x01\x06\x00\
+  \\x49\x0c\x54\x01\x06\x00\xbb\x0c\xfd\x00\x06\x00\xc7\x0c\xfd\x00\x06\x00\x1b\x0d\
+  \\x5c\x01\x06\x00\x1b\x0d\x5c\x01\x06\x00\xd4\x0d\xfd\x00\x50\x20\x00\x00\x00\x00\
+  \\x91\x18\x3d\x01\x16\x00\x01\x00\x28\x21\x00\x00\x00\x00\x96\x00\x44\x01\x1a\x00\
+  \\x01\x00\x34\x21\x00\x00\x00\x00\x96\x00\x49\x01\x1e\x00\x01\x00\x6b\x21\x00\x00\
+  \\x00\x00\x96\x00\x5c\x01\x23\x00\x02\x00\x9c\x21\x00\x00\x00\x00\x96\x00\x83\x01\
+  \\x16\x00\x03\x00\xe0\x21\x00\x00\x00\x00\x96\x00\x97\x01\x2c\x00\x03\x00\x2c\x22\
+  \\x00\x00\x00\x00\x96\x00\xa5\x01\x1e\x00\x06\x00\x48\x22\x00\x00\x00\x00\x96\x00\
+  \\xc0\x01\x33\x00\x07\x00\x68\x22\x00\x00\x00\x00\x96\x00\xd0\x01\x33\x00\x09\x00\
+  \\x88\x22\x00\x00\x00\x00\x96\x00\xe0\x01\x1e\x00\x0b\x00\xa4\x22\x00\x00\x00\x00\
+  \\x96\x00\x24\x02\x44\x00\x0c\x00\x10\x23\x00\x00\x00\x00\x96\x00\x33\x02\x49\x00\
+  \\x0d\x00\x88\x23\x00\x00\x00\x00\x96\x00\x54\x02\x52\x00\x0e\x00\xc8\x23\x00\x00\
+  \\x00\x00\x91\x00\x82\x02\x60\x00\x0f\x00\x10\x24\x00\x00\x00\x00\x96\x00\x9d\x02\
+  \\x23\x00\x10\x00\x50\x24\x00\x00\x00\x00\x91\x00\xae\x02\x66\x00\x11\x00\x54\x25\
+  \\x00\x00\x00\x00\x96\x00\xe6\x02\x6f\x00\x14\x00\x8c\x26\x00\x00\x00\x00\x96\x00\
+  \\x09\x03\x75\x00\x15\x00\x08\x28\x00\x00\x00\x00\x96\x00\x21\x03\x7b\x00\x16\x00\
+  \\x34\x29\x00\x00\x00\x00\x96\x00\x4b\x03\x81\x00\x17\x00\x54\x2a\x00\x00\x00\x00\
+  \\x96\x00\x60\x03\x81\x00\x18\x00\x6c\x2b\x00\x00\x00\x00\x96\x00\x75\x03\x7b\x00\
+  \\x19\x00\xd4\x2b\x00\x00\x00\x00\x91\x00\x85\x03\x87\x00\x1a\x00\x00\x2c\x00\x00\
+  \\x00\x00\x91\x00\xd0\x03\x8d\x00\x1b\x00\x2b\x2c\x00\x00\x00\x00\x91\x00\xde\x03\
+  \\x98\x00\x1c\x00\x3f\x2c\x00\x00\x00\x00\x91\x00\xf1\x03\xa1\x00\x1d\x00\x55\x2c\
+  \\x00\x00\x00\x00\x91\x00\x0f\x04\xa8\x00\x1e\x00\x65\x2c\x00\x00\x00\x00\x91\x00\
+  \\x24\x04\xb1\x00\x21\x00\x8c\x2c\x00\x00\x00\x00\x91\x00\x0f\x04\xb9\x00\x23\x00\
+  \\xe8\x2c\x00\x00\x00\x00\x91\x00\x4d\x04\xb1\x00\x26\x00\x18\x2d\x00\x00\x00\x00\
+  \\x91\x00\x58\x04\xc6\x00\x28\x00\x40\x2d\x00\x00\x00\x00\x91\x00\x82\x04\xa1\x00\
+  \\x2a\x00\xac\x2d\x00\x00\x00\x00\x91\x00\x99\x04\xd7\x00\x2b\x00\x20\x30\x00\x00\
+  \\x00\x00\x86\x18\xb3\x04\xdf\x00\x2d\x00\x00\x00\x00\x00\x03\x00\x86\x18\xb3\x04\
+  \\xe3\x00\x2d\x00\x00\x00\x00\x00\x03\x00\xc6\x01\xb9\x04\xe9\x00\x2f\x00\x00\x00\
+  \\x00\x00\x03\x00\xc6\x01\xdb\x04\xee\x00\x30\x00\x00\x00\x00\x00\x03\x00\xc6\x01\
+  \\xe7\x04\xf7\x00\x33\x00\x28\x30\x00\x00\x00\x00\x86\x08\x0d\x05\x06\x01\x34\x00\
+  \\x30\x30\x00\x00\x00\x00\x86\x08\x1c\x05\x0b\x01\x34\x00\x38\x30\x00\x00\x00\x00\
+  \\x86\x18\xb3\x04\x11\x01\x34\x00\x48\x30\x00\x00\x00\x00\xc6\x00\x2f\x05\x1a\x01\
+  \\x36\x00\xa8\x30\x00\x00\x00\x00\x96\x00\x38\x05\x1e\x01\x36\x00\xd8\x30\x00\x00\
+  \\x00\x00\x86\x00\x58\x05\x06\x01\x37\x00\x48\x31\x00\x00\x00\x00\x81\x00\x67\x05\
+  \\x25\x01\x37\x00\xb9\x32\x00\x00\x00\x00\x91\x18\x3d\x01\x16\x00\x38\x00\x00\x00\
+  \\x00\x00\x03\x00\x86\x18\xb3\x04\xe3\x00\x38\x00\x00\x00\x00\x00\x03\x00\xc6\x01\
+  \\xb9\x04\x36\x01\x3a\x00\x00\x00\x00\x00\x03\x00\xc6\x01\xdb\x04\x3b\x01\x3b\x00\
+  \\x00\x00\x00\x00\x03\x00\xc6\x01\xe7\x04\xf7\x00\x3e\x00\x00\x00\x00\x00\x03\x00\
+  \\x86\x18\xb3\x04\xe3\x00\x3f\x00\x00\x00\x00\x00\x03\x00\xc6\x01\xb9\x04\x44\x01\
+  \\x41\x00\x00\x00\x00\x00\x03\x00\xc6\x01\xdb\x04\x4a\x01\x42\x00\x00\x00\x00\x00\
+  \\x03\x00\xc6\x01\xe7\x04\xf7\x00\x45\x00\xc8\x32\x00\x00\x00\x00\x91\x18\x3d\x01\
+  \\x16\x00\x46\x00\xd5\x33\x00\x00\x00\x00\x96\x00\x9b\x06\x60\x01\x46\x00\xe8\x33\
+  \\x00\x00\x00\x00\x96\x00\xa8\x06\x66\x01\x47\x00\x2c\x34\x00\x00\x00\x00\x96\x00\
+  \\xb6\x06\x6d\x01\x48\x00\x84\x34\x00\x00\x00\x00\x96\x00\xb6\x06\x7a\x01\x4a\x00\
+  \\xc4\x34\x00\x00\x00\x00\x96\x00\xc4\x06\x86\x01\x4c\x00\x05\x35\x00\x00\x00\x00\
+  \\x96\x00\xcd\x06\x98\x01\x4e\x00\x2c\x35\x00\x00\x00\x00\x96\x00\xe2\x06\xa1\x01\
+  \\x4f\x00\xde\x33\x00\x00\x00\x00\x91\x00\x25\x11\x60\x01\x51\x00\xfd\x34\x00\x00\
+  \\x00\x00\x91\x00\x86\x11\x58\x05\x52\x00\x00\x00\x00\x00\x03\x00\x86\x18\xb3\x04\
+  \\xe3\x00\x53\x00\x00\x00\x00\x00\x03\x00\xc6\x01\xb9\x04\xa8\x01\x55\x00\x00\x00\
+  \\x00\x00\x03\x00\xc6\x01\xdb\x04\xaf\x01\x56\x00\x00\x00\x00\x00\x03\x00\xc6\x01\
+  \\xe7\x04\xb9\x01\x59\x00\xc1\x24\x00\x00\x00\x00\x86\x18\xb3\x04\xdf\x00\x5a\x00\
+  \\xcc\x24\x00\x00\x00\x00\x86\x00\x52\x0b\x44\x01\x5a\x00\xfb\x25\x00\x00\x00\x00\
+  \\x86\x18\xb3\x04\xdf\x00\x5b\x00\x04\x26\x00\x00\x00\x00\x86\x00\x4e\x0c\x44\x01\
+  \\x5b\x00\x49\x27\x00\x00\x00\x00\x86\x18\xb3\x04\xdf\x00\x5c\x00\x54\x27\x00\x00\
+  \\x00\x00\x86\x00\xd4\x0c\x44\x01\x5c\x00\x8c\x28\x00\x00\x00\x00\x86\x18\xb3\x04\
+  \\xdf\x00\x5d\x00\x94\x28\x00\x00\x00\x00\x86\x00\x21\x0d\x44\x01\x5d\x00\xcb\x29\
+  \\x00\x00\x00\x00\x86\x18\xb3\x04\xdf\x00\x5e\x00\xd4\x29\x00\x00\x00\x00\x86\x00\
+  \\x93\x0d\x44\x01\x5e\x00\x0e\x2b\x00\x00\x00\x00\x86\x18\xb3\x04\xdf\x00\x5f\x00\
+  \\x18\x2b\x00\x00\x00\x00\x86\x00\xde\x0d\x44\x01\x5f\x00\x00\x00\x01\x00\xfe\x08\
+  \\x00\x00\x01\x00\x49\x09\x00\x00\x01\x00\x02\x0a\x00\x00\x02\x00\xfe\x08\x00\x00\
+  \\x03\x00\x0c\x0a\x00\x00\x01\x00\x2e\x0a\x00\x00\x01\x00\x02\x0a\x00\x00\x02\x00\
+  \\x3f\x0a\x00\x00\x01\x00\x02\x0a\x00\x00\x02\x00\x3f\x0a\x00\x00\x01\x00\x52\x0a\
+  \\x00\x00\x01\x00\x5b\x0a\x00\x00\x01\x00\x81\x0a\x00\x00\x01\x00\x81\x0a\x00\x00\
+  \\x01\x00\x9e\x0a\x00\x00\x01\x00\xbe\x0a\x00\x00\x01\x00\xfe\x08\x00\x00\x02\x00\
+  \\xc5\x0a\x00\x00\x03\x00\xd5\x0a\x00\x00\x01\x00\x4e\x0b\x00\x00\x01\x00\x49\x0c\
+  \\x00\x00\x01\x00\xc7\x0c\x00\x00\x01\x00\x1b\x0d\x00\x00\x01\x00\x1b\x0d\x00\x00\
+  \\x01\x00\xd4\x0d\x00\x00\x01\x00\xf8\x0d\x00\x00\x01\x00\xf8\x0d\x00\x00\x01\x00\
+  \\x0a\x0e\x00\x00\x01\x00\x49\x0b\x00\x00\x01\x00\x70\x0b\x00\x00\x02\x00\x10\x0e\
+  \\x00\x00\x03\x00\x1e\x0e\x00\x00\x01\x00\x70\x0b\x00\x00\x02\x00\x2c\x0e\x00\x00\
+  \\x01\x00\x70\x0b\x00\x00\x02\x00\x40\x0e\x00\x00\x03\x00\x51\x0e\x00\x00\x01\x00\
+  \\x70\x0b\x00\x00\x02\x00\x49\x0b\x00\x00\x01\x00\x70\x0b\x00\x00\x02\x00\xc4\x0e\
+  \\x00\x00\x01\x00\xc7\x0c\x00\x00\x01\x00\xd8\x0e\x00\x00\x02\x00\xc7\x0c\x00\x00\
+  \\x01\x00\xf0\x0f\x00\x00\x02\x00\xf7\x0f\x00\x00\x01\x00\x81\x0a\x00\x00\x01\x00\
+  \\x81\x0a\x00\x00\x02\x00\xfe\x0f\x00\x00\x03\x00\xf0\x0f\x00\x00\x01\x00\x07\x10\
+  \\x00\x00\x01\x00\x2f\x10\x00\x00\x02\x00\x3a\x10\x00\x00\x01\x00\xc7\x0c\x00\x00\
+  \\x01\x00\xd8\x0e\x00\x00\x01\x00\xf0\x0f\x00\x00\x02\x00\xf7\x0f\x00\x00\x01\x00\
+  \\xbe\x0a\x00\x00\x01\x00\xbe\x0a\x00\x00\x02\x00\xfe\x0f\x00\x00\x03\x00\xf0\x0f\
+  \\x00\x00\x01\x00\x07\x10\x00\x00\x01\x00\xf0\x0f\x00\x00\x02\x00\xf7\x0f\x00\x00\
+  \\x01\x00\x70\x0b\x00\x00\x01\x00\x70\x0b\x00\x00\x02\x00\xfe\x0f\x00\x00\x03\x00\
+  \\xf0\x0f\x00\x00\x01\x00\x07\x10\x00\x00\x01\x00\x1b\x11\x00\x00\x01\x00\x1b\x11\
+  \\x00\x00\x01\x00\x7b\x11\x00\x00\x02\x00\x7d\x11\x00\x00\x01\x00\x7f\x11\x00\x00\
+  \\x02\x00\x7d\x11\x00\x00\x01\x00\x81\x11\x00\x00\x02\x00\x83\x11\x00\x00\x01\x00\
+  \\xc7\x11\x00\x00\x01\x00\x70\x0b\x00\x00\x02\x00\x10\x0e\x00\x00\x01\x00\xf8\x0d\
+  \\x00\x00\x01\x00\xc5\x11\x00\x00\x01\x00\xf0\x0f\x00\x00\x02\x00\xf7\x0f\x00\x00\
+  \\x01\x00\xf0\x11\x00\x00\x01\x00\xf0\x11\x00\x00\x02\x00\xfe\x0f\x00\x00\x03\x00\
+  \\xf0\x0f\x00\x00\x01\x00\x07\x10\x00\x00\x01\x00\x70\x0b\x00\x00\x01\x00\x70\x0b\
+  \\x00\x00\x01\x00\x70\x0b\x00\x00\x01\x00\x70\x0b\x00\x00\x01\x00\x70\x0b\x00\x00\
+  \\x01\x00\x70\x0b\xa1\x00\xb3\x04\xc0\x01\xa9\x00\xb3\x04\xc0\x01\xb1\x00\xb3\x04\
+  \\xc0\x01\xb9\x00\xb3\x04\xc0\x01\xc1\x00\xb3\x04\xc0\x01\xc9\x00\xb3\x04\xc0\x01\
+  \\xd1\x00\xb3\x04\xe9\x00\xd9\x00\xb3\x04\xdf\x00\x0c\x00\xb3\x04\xdf\x00\x14\x00\
+  \\xb3\x04\xdf\x00\x1c\x00\xb3\x04\xdf\x00\xe1\x00\x19\x08\xdc\x01\xf1\x00\xb3\x04\
+  \\xdf\x00\xe9\x00\x4a\x08\xe1\x01\x01\x01\x6f\x08\x16\x00\x09\x01\x8c\x08\xe7\x01\
+  \\x11\x01\xb3\x04\xc0\x01\x09\x01\xc1\x08\xed\x01\x21\x00\xd7\x08\xf8\x01\x29\x00\
+  \\xeb\x08\xff\x01\x0c\x00\x4a\x08\x05\x02\x59\x00\x1b\x09\x0d\x02\x59\x00\x2d\x09\
+  \\x15\x02\x31\x01\xb3\x04\x1b\x02\x39\x01\x62\x09\x26\x02\x39\x01\x67\x09\x29\x02\
+  \\x41\x01\x7b\x09\x2f\x02\x31\x00\x99\x09\x06\x01\x49\x01\xab\x09\x1a\x01\x51\x01\
+  \\xd1\x09\x37\x02\x59\x01\xe4\x09\x3c\x02\x61\x01\xf3\x09\x42\x02\x21\x00\xfd\x09\
+  \\xc0\x01\x59\x01\x67\x09\x4b\x02\x59\x00\x1f\x0a\x51\x02\x59\x00\x2d\x09\x59\x02\
+  \\x59\x00\x49\x0a\x6e\x02\x69\x01\x76\x0a\x7f\x02\x69\x01\x7c\x0a\x7f\x02\x0c\x00\
+  \\x85\x0a\x8f\x02\x59\x01\xe4\x09\x98\x02\x31\x01\xb3\x04\xc0\x01\x0c\x00\x97\x0a\
+  \\xa9\x02\x41\x01\xa0\x0a\x60\x00\x14\x00\x4a\x08\x05\x02\x14\x00\x97\x0a\xa9\x02\
+  \\x31\x00\xfd\x0a\xcd\x02\x79\x01\x0a\x0b\xdc\x02\x89\x01\xb3\x04\xe1\x02\x89\x01\
+  \\x0a\x0b\xdc\x02\x89\x01\x27\x0b\xed\x02\x09\x00\xb3\x04\xdf\x00\x79\x00\x81\x0b\
+  \\xfd\x02\x99\x01\x9d\x0b\x05\x03\x79\x00\xa6\x0b\x0a\x03\x99\x01\xab\x0b\x05\x03\
+  \\x79\x00\xa6\x0b\x12\x03\x99\x01\xb3\x0b\x05\x03\x79\x00\xa6\x0b\x1b\x03\xa9\x01\
+  \\xc6\x0b\x22\x03\x99\x01\xd4\x0b\x05\x03\x79\x00\xa6\x0b\x28\x03\x99\x01\xdb\x0b\
+  \\x05\x03\xb1\x01\xea\x0b\x06\x01\x59\x00\xfc\x0b\x31\x03\xb9\x01\xb3\x04\xc0\x01\
+  \\x59\x00\x22\x0c\x01\x01\xb1\x01\x2d\x0c\x1a\x01\xa9\x01\x67\x0c\x31\x03\x99\x01\
+  \\x74\x0c\x05\x03\x79\x00\xa6\x0b\x3c\x03\x99\x01\x79\x0c\x05\x03\x51\x00\x82\x0c\
+  \\x45\x03\x89\x00\x96\x0c\x06\x01\x59\x01\xe4\x09\x4f\x03\x99\x01\xfa\x0c\x05\x03\
+  \\x99\x01\x02\x0d\x05\x03\x61\x00\x67\x0c\x31\x03\x61\x00\x3c\x0d\x31\x03\x61\x00\
+  \\x4a\x0d\x72\x03\x99\x01\x5e\x0d\x05\x03\x79\x00\xa6\x0b\x76\x03\x99\x01\x65\x0d\
+  \\x05\x03\x79\x00\xa6\x0b\x7e\x03\x99\x01\x6c\x0d\x05\x03\x61\x00\x72\x0d\x06\x01\
+  \\x99\x01\xae\x0d\x05\x03\x99\x01\xb5\x0d\x05\x03\x99\x01\xf4\x0d\x05\x03\x59\x00\
+  \\xfa\x0d\x31\x03\x2c\x00\xb3\x04\xb3\x03\x34\x00\xb3\x04\xe3\x00\x99\x01\x36\x0e\
+  \\x05\x03\x3c\x00\x6e\x0e\xd9\x03\x44\x00\x7c\x0e\xeb\x03\xd1\x01\xa7\x0e\x31\x03\
+  \\xd9\x01\xbc\x0e\xdf\x00\x1c\x00\x85\x0a\x8f\x02\x1c\x00\x4a\x08\x05\x02\x29\x00\
+  \\xeb\x08\x0e\x04\x31\x00\x09\x0f\x17\x04\x31\x00\x3b\x0f\x23\x04\xf9\x01\x0a\x0b\
+  \\xdc\x02\x99\x01\x4d\x0f\x05\x03\x99\x01\x55\x0f\x05\x03\x99\x01\x5d\x0f\x05\x03\
+  \\x31\x00\xfd\x0a\x32\x04\x79\x01\x7c\x0f\x3c\x04\x79\x00\x99\x0f\x43\x04\x99\x01\
+  \\xa5\x0f\x05\x03\x99\x01\xae\x0f\x05\x03\x79\x00\xa6\x0b\x49\x04\x79\x00\xb2\x0f\
+  \\x53\x04\x19\x02\xb3\x04\x7e\x04\x29\x02\xb3\x04\x8e\x04\x39\x02\xb3\x04\xdf\x00\
+  \\x39\x02\x63\x10\x95\x04\x09\x00\x2f\x05\x1a\x01\x51\x00\x0d\x05\x06\x01\x29\x00\
+  \\xeb\x08\xa8\x04\x41\x02\xb3\x04\xb3\x04\x31\x00\x81\x10\xbb\x04\xf9\x01\x7c\x0f\
+  \\x3c\x04\x2c\x00\x94\x10\x31\x03\x79\x01\xc6\x10\xc2\x04\x2c\x00\xe9\x10\xeb\x03\
+  \\x49\x02\x81\x10\xbb\x04\x61\x02\xb3\x04\xdf\x00\x59\x00\x49\x0a\xf4\x04\x59\x00\
+  \\x2d\x09\xfd\x04\x59\x00\x1d\x11\x06\x05\x4c\x00\xb3\x04\xe3\x00\x59\x01\x75\x11\
+  \\x1e\x05\x64\x00\xb9\x04\xa8\x01\x6c\x00\xb3\x04\xe3\x00\x99\x01\xd2\x11\x05\x03\
+  \\x99\x01\xda\x11\x05\x03\x99\x01\xe2\x11\x05\x03\x99\x01\xea\x11\x05\x03\x2e\x00\
+  \\x2b\x00\xbe\x05\x2e\x00\x3b\x00\xdb\x05\x2e\x00\x43\x00\xe4\x05\x2e\x00\x33\x00\
+  \\xb3\x05\x2e\x00\x0b\x00\x79\x05\x2e\x00\x1b\x00\x86\x05\x2e\x00\x23\x00\xb3\x05\
+  \\x63\x00\x93\x03\x85\x04\xa3\x00\x93\x03\x85\x04\x43\x01\x03\x04\xef\x04\x63\x01\
+  \\x03\x04\xef\x04\x83\x01\x03\x04\xef\x04\xa3\x01\x03\x04\xef\x04\xc3\x01\x03\x04\
+  \\xef\x04\xe3\x01\x03\x04\xef\x04\xe1\x02\x03\x04\xef\x04\x01\x03\x03\x04\xef\x04\
+  \\xe0\x07\x03\x04\xef\x04\x00\x08\x03\x04\xef\x04\x21\x02\x47\x02\x62\x02\x69\x02\
+  \\x74\x02\x84\x02\x9e\x02\xaf\x02\xb8\x02\xc3\x02\xf4\x02\x35\x03\x56\x03\x5f\x03\
+  \\x68\x03\x87\x03\x8b\x03\x95\x03\xa2\x03\xb9\x03\xf0\x03\xff\x03\x5a\x04\x9c\x04\
+  \\xcd\x04\x2e\x05\x36\x05\x3e\x05\x51\x05\x04\x00\x01\x00\x00\x00\x7a\x05\x2b\x01\
+  \\x00\x00\x85\x05\x30\x01\x02\x00\x27\x00\x03\x00\x02\x00\x28\x00\x05\x00\xc5\x01\
+  \\xcc\x01\xd4\x01\x79\x02\xac\x03\xc2\x03\xd2\x03\xe3\x03\x16\x05\x33\x05\x45\x05\
+  \\x48\x05\x69\x05\x04\x80\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x1b\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\
+  \\x8c\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\
+  \\x95\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\
+  \\x4e\x08\x00\x00\x00\x00\x03\x00\x02\x00\x04\x00\x02\x00\x09\x00\x08\x00\x0a\x00\
+  \\x02\x00\x0b\x00\x02\x00\x0c\x00\x02\x00\x0d\x00\x02\x00\x0e\x00\x02\x00\x0f\x00\
+  \\x02\x00\x00\x00\x00\x00\x12\x00\xbf\x00\x01\x00\x00\x00\x12\x00\xc1\x00\x00\x00\
+  \\x00\x00\x75\x00\xc2\x06\x00\x00\x00\x00\x77\x00\xc2\x06\x00\x00\x00\x00\x79\x00\
+  \\xbf\x00\x01\x00\x00\x00\x79\x00\xc1\x00\x76\x00\x4a\x03\x78\x00\xcb\x03\x78\x00\
+  \\x28\x05\x78\x00\x72\x05\x00\x00\x00\x3c\x4d\x6f\x64\x75\x6c\x65\x3e\x00\x53\x61\
+  \\x6c\x73\x61\x2e\x64\x6c\x6c\x00\x44\x72\x69\x76\x65\x72\x00\x53\x61\x6c\x73\x61\
+  \\x00\x52\x65\x6c\x65\x61\x73\x65\x4f\x62\x6a\x65\x63\x74\x44\x65\x6c\x65\x67\x61\
+  \\x74\x65\x00\x44\x65\x6c\x65\x67\x61\x74\x65\x53\x69\x67\x6e\x61\x74\x75\x72\x65\
+  \\x00\x46\x72\x65\x65\x48\x61\x73\x6b\x65\x6c\x6c\x46\x75\x6e\x50\x74\x72\x44\x65\
+  \\x6c\x65\x67\x61\x74\x65\x00\x49\x4c\x57\x72\x69\x74\x65\x72\x44\x65\x6c\x65\x67\
+  \\x61\x74\x65\x00\x4d\x65\x6d\x62\x65\x72\x49\x6e\x66\x6f\x73\x00\x55\x74\x69\x6c\
+  \\x00\x46\x75\x6e\x63\x60\x32\x00\x6d\x73\x63\x6f\x72\x6c\x69\x62\x00\x53\x79\x73\
+  \\x74\x65\x6d\x00\x4f\x62\x6a\x65\x63\x74\x00\x4d\x75\x6c\x74\x69\x63\x61\x73\x74\
+  \\x44\x65\x6c\x65\x67\x61\x74\x65\x00\x56\x61\x6c\x75\x65\x54\x79\x70\x65\x00\x41\
+  \\x00\x42\x00\x53\x79\x73\x74\x65\x6d\x2e\x52\x65\x66\x6c\x65\x63\x74\x69\x6f\x6e\
+  \\x2e\x45\x6d\x69\x74\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x42\x75\x69\x6c\x64\x65\
+  \\x72\x00\x5f\x61\x73\x73\x65\x6d\x62\x6c\x79\x42\x75\x69\x6c\x64\x65\x72\x00\x4d\
+  \\x6f\x64\x75\x6c\x65\x42\x75\x69\x6c\x64\x65\x72\x00\x5f\x64\x79\x6e\x61\x6d\x69\
+  \\x63\x4d\x6f\x64\x75\x6c\x65\x42\x75\x69\x6c\x64\x65\x72\x00\x54\x79\x70\x65\x42\
+  \\x75\x69\x6c\x64\x65\x72\x00\x5f\x73\x74\x75\x62\x73\x54\x79\x70\x65\x42\x75\x69\
+  \\x6c\x64\x65\x72\x00\x2e\x63\x63\x74\x6f\x72\x00\x42\x6f\x6f\x74\x00\x47\x65\x74\
+  \\x50\x6f\x69\x6e\x74\x65\x72\x54\x6f\x4d\x65\x74\x68\x6f\x64\x00\x53\x65\x74\x46\
+  \\x72\x65\x65\x48\x61\x73\x6b\x65\x6c\x6c\x46\x75\x6e\x50\x74\x72\x00\x46\x72\x65\
+  \\x65\x48\x61\x73\x6b\x65\x6c\x6c\x46\x75\x6e\x50\x74\x72\x00\x53\x61\x76\x65\x44\
+  \\x79\x6e\x61\x6d\x69\x63\x41\x73\x73\x65\x6d\x62\x6c\x79\x00\x47\x65\x74\x4d\x65\
+  \\x74\x68\x6f\x64\x53\x74\x75\x62\x00\x47\x65\x74\x44\x65\x6c\x65\x67\x61\x74\x65\
+  \\x43\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x53\x74\x75\x62\x00\x47\x65\x74\x46\
+  \\x69\x65\x6c\x64\x47\x65\x74\x53\x74\x75\x62\x00\x47\x65\x74\x46\x69\x65\x6c\x64\
+  \\x53\x65\x74\x53\x74\x75\x62\x00\x47\x65\x74\x42\x6f\x78\x53\x74\x75\x62\x00\x53\
+  \\x79\x73\x74\x65\x6d\x2e\x43\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\x73\x2e\x47\x65\
+  \\x6e\x65\x72\x69\x63\x00\x44\x69\x63\x74\x69\x6f\x6e\x61\x72\x79\x60\x32\x00\x5f\
+  \\x69\x6e\x54\x61\x62\x6c\x65\x00\x5f\x6e\x65\x78\x74\x49\x64\x00\x52\x65\x67\x69\
+  \\x73\x74\x65\x72\x4f\x62\x6a\x65\x63\x74\x00\x47\x65\x74\x4f\x62\x6a\x65\x63\x74\
+  \\x00\x5f\x52\x65\x6c\x65\x61\x73\x65\x4f\x62\x6a\x65\x63\x74\x44\x65\x6c\x65\x67\
+  \\x61\x74\x65\x00\x52\x65\x6c\x65\x61\x73\x65\x4f\x62\x6a\x65\x63\x74\x00\x44\x65\
+  \\x6c\x65\x67\x61\x74\x65\x00\x5f\x64\x6f\x74\x4e\x65\x74\x46\x75\x6e\x50\x74\x72\
+  \\x44\x65\x6c\x65\x67\x61\x74\x65\x73\x00\x47\x65\x74\x44\x6f\x74\x4e\x65\x74\x46\
+  \\x75\x6e\x50\x74\x72\x46\x6f\x72\x44\x65\x6c\x65\x67\x61\x74\x65\x00\x46\x72\x65\
+  \\x65\x44\x6f\x74\x4e\x65\x74\x46\x75\x6e\x50\x74\x72\x00\x47\x65\x6e\x65\x72\x61\
+  \\x74\x65\x44\x79\x6e\x61\x6d\x69\x63\x4d\x65\x74\x68\x6f\x64\x00\x53\x79\x73\x74\
+  \\x65\x6d\x2e\x52\x65\x66\x6c\x65\x63\x74\x69\x6f\x6e\x00\x43\x6f\x6e\x73\x74\x72\
+  \\x75\x63\x74\x6f\x72\x49\x6e\x66\x6f\x00\x47\x65\x6e\x65\x72\x61\x74\x65\x43\x6f\
+  \\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x53\x74\x75\x62\x00\x4d\x65\x74\x68\x6f\x64\
+  \\x49\x6e\x66\x6f\x00\x47\x65\x6e\x65\x72\x61\x74\x65\x4d\x65\x74\x68\x6f\x64\x53\
+  \\x74\x75\x62\x00\x54\x79\x70\x65\x00\x47\x65\x6e\x65\x72\x61\x74\x65\x44\x65\x6c\
+  \\x65\x67\x61\x74\x65\x43\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x53\x74\x75\x62\
+  \\x00\x46\x69\x65\x6c\x64\x49\x6e\x66\x6f\x00\x47\x65\x6e\x65\x72\x61\x74\x65\x46\
+  \\x69\x65\x6c\x64\x47\x65\x74\x53\x74\x75\x62\x00\x47\x65\x6e\x65\x72\x61\x74\x65\
+  \\x46\x69\x65\x6c\x64\x53\x65\x74\x53\x74\x75\x62\x00\x47\x65\x6e\x65\x72\x61\x74\
+  \\x65\x42\x6f\x78\x53\x74\x75\x62\x00\x49\x73\x4d\x61\x72\x73\x68\x61\x6c\x65\x64\
+  \\x42\x79\x49\x6e\x64\x65\x78\x00\x4e\x75\x6c\x6c\x61\x62\x6c\x65\x60\x31\x00\x53\
+  \\x79\x73\x74\x65\x6d\x2e\x52\x75\x6e\x74\x69\x6d\x65\x2e\x49\x6e\x74\x65\x72\x6f\
+  \\x70\x53\x65\x72\x76\x69\x63\x65\x73\x00\x55\x6e\x6d\x61\x6e\x61\x67\x65\x64\x54\
+  \\x79\x70\x65\x00\x4d\x61\x72\x73\x68\x61\x6c\x54\x79\x70\x65\x41\x73\x00\x43\x6f\
+  \\x6e\x76\x65\x72\x74\x54\x6f\x53\x74\x75\x62\x54\x79\x70\x65\x73\x00\x43\x6f\x6e\
+  \\x76\x65\x72\x74\x54\x6f\x53\x74\x75\x62\x54\x79\x70\x65\x00\x49\x4c\x47\x65\x6e\
+  \\x65\x72\x61\x74\x6f\x72\x00\x45\x6d\x69\x74\x50\x61\x72\x61\x6d\x65\x74\x65\x72\
+  \\x4c\x6f\x61\x64\x69\x6e\x67\x00\x45\x6d\x69\x74\x46\x72\x6f\x6d\x53\x74\x75\x62\
+  \\x00\x49\x45\x6e\x75\x6d\x65\x72\x61\x62\x6c\x65\x60\x31\x00\x50\x61\x72\x61\x6d\
+  \\x65\x74\x65\x72\x49\x6e\x66\x6f\x00\x45\x6d\x69\x74\x54\x6f\x53\x74\x75\x62\x00\
+  \\x45\x6d\x69\x74\x4d\x61\x72\x73\x68\x61\x6c\x65\x64\x52\x65\x74\x75\x72\x6e\x00\
+  \\x5f\x64\x65\x6c\x65\x67\x61\x74\x65\x57\x72\x61\x70\x70\x65\x72\x54\x79\x70\x65\
+  \\x73\x00\x47\x65\x74\x44\x65\x6c\x65\x67\x61\x74\x65\x57\x72\x61\x70\x70\x65\x72\
+  \\x54\x79\x70\x65\x00\x43\x72\x65\x61\x74\x65\x44\x65\x6c\x65\x67\x61\x74\x65\x57\
+  \\x72\x61\x70\x70\x65\x72\x54\x79\x70\x65\x00\x2e\x63\x74\x6f\x72\x00\x49\x6e\x76\
+  \\x6f\x6b\x65\x00\x49\x41\x73\x79\x6e\x63\x52\x65\x73\x75\x6c\x74\x00\x41\x73\x79\
+  \\x6e\x63\x43\x61\x6c\x6c\x62\x61\x63\x6b\x00\x42\x65\x67\x69\x6e\x49\x6e\x76\x6f\
+  \\x6b\x65\x00\x45\x6e\x64\x49\x6e\x76\x6f\x6b\x65\x00\x5f\x72\x65\x74\x75\x72\x6e\
+  \\x54\x79\x70\x65\x00\x5f\x70\x61\x72\x61\x6d\x65\x74\x65\x72\x54\x79\x70\x65\x73\
+  \\x00\x67\x65\x74\x5f\x52\x65\x74\x75\x72\x6e\x54\x79\x70\x65\x00\x67\x65\x74\x5f\
+  \\x50\x61\x72\x61\x6d\x65\x74\x65\x72\x54\x79\x70\x65\x73\x00\x54\x6f\x53\x74\x72\
+  \\x69\x6e\x67\x00\x46\x72\x6f\x6d\x44\x65\x6c\x65\x67\x61\x74\x65\x54\x79\x70\x65\
+  \\x00\x5f\x64\x65\x6c\x65\x67\x61\x74\x65\x54\x79\x70\x65\x73\x00\x54\x6f\x44\x65\
+  \\x6c\x65\x67\x61\x74\x65\x54\x79\x70\x65\x00\x43\x72\x65\x61\x74\x65\x44\x65\x6c\
+  \\x65\x67\x61\x74\x65\x54\x79\x70\x65\x00\x52\x65\x74\x75\x72\x6e\x54\x79\x70\x65\
+  \\x00\x50\x61\x72\x61\x6d\x65\x74\x65\x72\x54\x79\x70\x65\x73\x00\x54\x79\x70\x65\
+  \\x5f\x47\x65\x74\x54\x79\x70\x65\x46\x72\x6f\x6d\x48\x61\x6e\x64\x6c\x65\x00\x4f\
+  \\x62\x6a\x65\x63\x74\x5f\x63\x74\x6f\x72\x00\x4d\x61\x72\x73\x68\x61\x6c\x5f\x47\
+  \\x65\x74\x44\x65\x6c\x65\x67\x61\x74\x65\x46\x6f\x72\x46\x75\x6e\x63\x74\x69\x6f\
+  \\x6e\x50\x6f\x69\x6e\x74\x65\x72\x00\x4d\x61\x72\x73\x68\x61\x6c\x5f\x47\x65\x74\
+  \\x46\x75\x6e\x63\x74\x69\x6f\x6e\x50\x6f\x69\x6e\x74\x65\x72\x46\x6f\x72\x44\x65\
+  \\x6c\x65\x67\x61\x74\x65\x00\x4d\x61\x72\x73\x68\x61\x6c\x5f\x53\x74\x72\x69\x6e\
+  \\x67\x54\x6f\x48\x47\x6c\x6f\x62\x61\x6c\x55\x6e\x69\x00\x4d\x61\x72\x73\x68\x61\
+  \\x6c\x5f\x53\x74\x72\x69\x6e\x67\x54\x6f\x48\x47\x6c\x6f\x62\x61\x6c\x41\x6e\x73\
+  \\x69\x00\x44\x72\x69\x76\x65\x72\x5f\x46\x72\x65\x65\x48\x61\x73\x6b\x65\x6c\x6c\
+  \\x46\x75\x6e\x50\x74\x72\x00\x44\x72\x69\x76\x65\x72\x5f\x52\x65\x67\x69\x73\x74\
+  \\x65\x72\x4f\x62\x6a\x65\x63\x74\x00\x44\x72\x69\x76\x65\x72\x5f\x47\x65\x74\x4f\
+  \\x62\x6a\x65\x63\x74\x00\x46\x72\x65\x65\x48\x61\x73\x6b\x65\x6c\x6c\x46\x75\x6e\
+  \\x50\x74\x72\x44\x65\x6c\x65\x67\x61\x74\x65\x5f\x49\x6e\x76\x6f\x6b\x65\x00\x53\
+  \\x74\x72\x69\x6e\x67\x54\x6f\x54\x79\x70\x65\x00\x53\x74\x72\x69\x6e\x67\x54\x6f\
+  \\x54\x79\x70\x65\x73\x00\x43\x6f\x6e\x63\x61\x74\x41\x72\x72\x61\x79\x00\x54\x00\
+  \\x4d\x61\x70\x41\x72\x72\x61\x79\x00\x4d\x61\x70\x50\x61\x72\x61\x6d\x65\x74\x65\
+  \\x72\x73\x54\x6f\x54\x79\x70\x65\x73\x00\x45\x6d\x69\x74\x4c\x64\x61\x72\x67\x00\
+  \\x41\x73\x73\x65\x6d\x62\x6c\x79\x46\x69\x6c\x65\x56\x65\x72\x73\x69\x6f\x6e\x41\
+  \\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x56\x65\x72\
+  \\x73\x69\x6f\x6e\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\
+  \\x6c\x79\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x41\x74\x74\x72\x69\x62\x75\x74\x65\
+  \\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x50\x72\x6f\x64\x75\x63\x74\x41\x74\x74\x72\
+  \\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x44\x65\x73\x63\x72\x69\
+  \\x70\x74\x69\x6f\x6e\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x41\x73\x73\x65\x6d\
+  \\x62\x6c\x79\x54\x69\x74\x6c\x65\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x53\x79\
+  \\x73\x74\x65\x6d\x2e\x52\x75\x6e\x74\x69\x6d\x65\x2e\x43\x6f\x6d\x70\x69\x6c\x65\
+  \\x72\x53\x65\x72\x76\x69\x63\x65\x73\x00\x43\x6f\x6d\x70\x69\x6c\x61\x74\x69\x6f\
+  \\x6e\x52\x65\x6c\x61\x78\x61\x74\x69\x6f\x6e\x73\x41\x74\x74\x72\x69\x62\x75\x74\
+  \\x65\x00\x52\x75\x6e\x74\x69\x6d\x65\x43\x6f\x6d\x70\x61\x74\x69\x62\x69\x6c\x69\
+  \\x74\x79\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x53\x79\x73\x74\x65\x6d\x2e\x44\
+  \\x69\x61\x67\x6e\x6f\x73\x74\x69\x63\x73\x00\x54\x72\x61\x63\x65\x00\x54\x72\x61\
+  \\x63\x65\x4c\x69\x73\x74\x65\x6e\x65\x72\x43\x6f\x6c\x6c\x65\x63\x74\x69\x6f\x6e\
+  \\x00\x67\x65\x74\x5f\x4c\x69\x73\x74\x65\x6e\x65\x72\x73\x00\x43\x6f\x6e\x73\x6f\
+  \\x6c\x65\x54\x72\x61\x63\x65\x4c\x69\x73\x74\x65\x6e\x65\x72\x00\x54\x72\x61\x63\
+  \\x65\x4c\x69\x73\x74\x65\x6e\x65\x72\x00\x41\x64\x64\x00\x53\x79\x73\x74\x65\x6d\
+  \\x2e\x57\x69\x6e\x64\x6f\x77\x73\x2e\x46\x6f\x72\x6d\x73\x00\x41\x70\x70\x6c\x69\
+  \\x63\x61\x74\x69\x6f\x6e\x00\x45\x6e\x61\x62\x6c\x65\x56\x69\x73\x75\x61\x6c\x53\
+  \\x74\x79\x6c\x65\x73\x00\x41\x70\x70\x44\x6f\x6d\x61\x69\x6e\x00\x67\x65\x74\x5f\
+  \\x43\x75\x72\x72\x65\x6e\x74\x44\x6f\x6d\x61\x69\x6e\x00\x41\x73\x73\x65\x6d\x62\
+  \\x6c\x79\x4e\x61\x6d\x65\x00\x41\x73\x73\x65\x6d\x62\x6c\x79\x42\x75\x69\x6c\x64\
+  \\x65\x72\x41\x63\x63\x65\x73\x73\x00\x44\x65\x66\x69\x6e\x65\x44\x79\x6e\x61\x6d\
+  \\x69\x63\x41\x73\x73\x65\x6d\x62\x6c\x79\x00\x44\x65\x66\x69\x6e\x65\x44\x79\x6e\
+  \\x61\x6d\x69\x63\x4d\x6f\x64\x75\x6c\x65\x00\x44\x65\x66\x69\x6e\x65\x54\x79\x70\
+  \\x65\x00\x42\x6f\x6f\x6c\x65\x61\x6e\x00\x6d\x65\x74\x68\x6f\x64\x4e\x61\x6d\x65\
+  \\x00\x52\x75\x6e\x74\x69\x6d\x65\x54\x79\x70\x65\x48\x61\x6e\x64\x6c\x65\x00\x47\
+  \\x65\x74\x54\x79\x70\x65\x46\x72\x6f\x6d\x48\x61\x6e\x64\x6c\x65\x00\x47\x65\x74\
+  \\x4d\x65\x74\x68\x6f\x64\x00\x41\x72\x67\x75\x6d\x65\x6e\x74\x45\x78\x63\x65\x70\
+  \\x74\x69\x6f\x6e\x00\x66\x72\x65\x65\x48\x61\x73\x6b\x65\x6c\x6c\x46\x75\x6e\x50\
+  \\x74\x72\x00\x49\x6e\x74\x50\x74\x72\x00\x5a\x65\x72\x6f\x00\x6f\x70\x5f\x45\x71\
+  \\x75\x61\x6c\x69\x74\x79\x00\x4d\x61\x72\x73\x68\x61\x6c\x00\x47\x65\x74\x44\x65\
+  \\x6c\x65\x67\x61\x74\x65\x46\x6f\x72\x46\x75\x6e\x63\x74\x69\x6f\x6e\x50\x6f\x69\
+  \\x6e\x74\x65\x72\x00\x43\x72\x65\x61\x74\x65\x54\x79\x70\x65\x00\x4d\x6f\x64\x75\
+  \\x6c\x65\x00\x67\x65\x74\x5f\x46\x75\x6c\x6c\x79\x51\x75\x61\x6c\x69\x66\x69\x65\
+  \\x64\x4e\x61\x6d\x65\x00\x53\x79\x73\x74\x65\x6d\x2e\x49\x4f\x00\x50\x61\x74\x68\
+  \\x00\x47\x65\x74\x46\x69\x6c\x65\x4e\x61\x6d\x65\x00\x53\x74\x72\x69\x6e\x67\x00\
+  \\x43\x6f\x6e\x63\x61\x74\x00\x43\x6f\x6e\x73\x6f\x6c\x65\x00\x57\x72\x69\x74\x65\
+  \\x4c\x69\x6e\x65\x00\x53\x61\x76\x65\x00\x63\x6c\x61\x73\x73\x4e\x61\x6d\x65\x00\
+  \\x70\x61\x72\x61\x6d\x65\x74\x65\x72\x54\x79\x70\x65\x4e\x61\x6d\x65\x73\x00\x47\
+  \\x65\x74\x43\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\x00\x64\x65\x6c\x65\x67\x61\
+  \\x74\x65\x54\x79\x70\x65\x4e\x61\x6d\x65\x00\x66\x69\x65\x6c\x64\x4e\x61\x6d\x65\
+  \\x00\x47\x65\x74\x46\x69\x65\x6c\x64\x00\x74\x79\x70\x65\x4e\x61\x6d\x65\x00\x6f\
+  \\x00\x53\x79\x73\x74\x65\x6d\x2e\x54\x68\x72\x65\x61\x64\x69\x6e\x67\x00\x4d\x6f\
+  \\x6e\x69\x74\x6f\x72\x00\x45\x6e\x74\x65\x72\x00\x45\x78\x69\x74\x00\x6f\x49\x64\
+  \\x00\x54\x72\x79\x47\x65\x74\x56\x61\x6c\x75\x65\x00\x49\x6e\x74\x33\x32\x00\x52\
+  \\x65\x6d\x6f\x76\x65\x00\x64\x00\x47\x65\x74\x46\x75\x6e\x63\x74\x69\x6f\x6e\x50\
+  \\x6f\x69\x6e\x74\x65\x72\x46\x6f\x72\x44\x65\x6c\x65\x67\x61\x74\x65\x00\x66\x75\
+  \\x6e\x50\x74\x72\x00\x6d\x65\x74\x68\x6f\x64\x53\x69\x67\x6e\x61\x74\x75\x72\x65\
+  \\x00\x69\x6c\x57\x72\x69\x74\x65\x72\x00\x4d\x65\x74\x68\x6f\x64\x42\x75\x69\x6c\
+  \\x64\x65\x72\x00\x4d\x65\x74\x68\x6f\x64\x41\x74\x74\x72\x69\x62\x75\x74\x65\x73\
+  \\x00\x44\x65\x66\x69\x6e\x65\x4d\x65\x74\x68\x6f\x64\x00\x47\x65\x74\x49\x4c\x47\
+  \\x65\x6e\x65\x72\x61\x74\x6f\x72\x00\x44\x79\x6e\x61\x6d\x69\x63\x4d\x65\x74\x68\
+  \\x6f\x64\x00\x43\x72\x65\x61\x74\x65\x44\x65\x6c\x65\x67\x61\x74\x65\x00\x3c\x3e\
+  \\x63\x5f\x5f\x44\x69\x73\x70\x6c\x61\x79\x43\x6c\x61\x73\x73\x31\x00\x74\x79\x70\
+  \\x65\x00\x63\x6f\x6e\x00\x3c\x47\x65\x6e\x65\x72\x61\x74\x65\x43\x6f\x6e\x73\x74\
+  \\x72\x75\x63\x74\x6f\x72\x53\x74\x75\x62\x3e\x62\x5f\x5f\x30\x00\x69\x6c\x67\x00\
+  \\x4c\x6f\x63\x61\x6c\x42\x75\x69\x6c\x64\x65\x72\x00\x44\x65\x63\x6c\x61\x72\x65\
+  \\x4c\x6f\x63\x61\x6c\x00\x4f\x70\x43\x6f\x64\x65\x73\x00\x4f\x70\x43\x6f\x64\x65\
+  \\x00\x4c\x64\x6c\x6f\x63\x61\x5f\x53\x00\x45\x6d\x69\x74\x00\x49\x6e\x69\x74\x6f\
+  \\x62\x6a\x00\x4c\x64\x6c\x6f\x63\x5f\x30\x00\x4d\x65\x74\x68\x6f\x64\x42\x61\x73\
+  \\x65\x00\x47\x65\x74\x50\x61\x72\x61\x6d\x65\x74\x65\x72\x73\x00\x4e\x65\x77\x6f\
+  \\x62\x6a\x00\x52\x65\x74\x00\x4d\x65\x6d\x62\x65\x72\x49\x6e\x66\x6f\x00\x67\x65\
+  \\x74\x5f\x44\x65\x63\x6c\x61\x72\x69\x6e\x67\x54\x79\x70\x65\x00\x67\x65\x74\x5f\
+  \\x49\x73\x56\x61\x6c\x75\x65\x54\x79\x70\x65\x00\x41\x72\x67\x75\x6d\x65\x6e\x74\
+  \\x4e\x75\x6c\x6c\x45\x78\x63\x65\x70\x74\x69\x6f\x6e\x00\x45\x6d\x70\x74\x79\x54\
+  \\x79\x70\x65\x73\x00\x67\x65\x74\x5f\x4e\x61\x6d\x65\x00\x3c\x3e\x63\x5f\x5f\x44\
+  \\x69\x73\x70\x6c\x61\x79\x43\x6c\x61\x73\x73\x34\x00\x6d\x65\x74\x68\x00\x3c\x47\
+  \\x65\x6e\x65\x72\x61\x74\x65\x4d\x65\x74\x68\x6f\x64\x53\x74\x75\x62\x3e\x62\x5f\
+  \\x5f\x33\x00\x67\x65\x74\x5f\x49\x73\x53\x74\x61\x74\x69\x63\x00\x43\x61\x6c\x6c\
+  \\x00\x43\x61\x6c\x6c\x76\x69\x72\x74\x00\x67\x65\x74\x5f\x52\x65\x74\x75\x72\x6e\
+  \\x50\x61\x72\x61\x6d\x65\x74\x65\x72\x00\x67\x65\x74\x5f\x50\x61\x72\x61\x6d\x65\
+  \\x74\x65\x72\x54\x79\x70\x65\x00\x3c\x3e\x63\x5f\x5f\x44\x69\x73\x70\x6c\x61\x79\
+  \\x43\x6c\x61\x73\x73\x37\x00\x77\x72\x61\x70\x70\x65\x72\x54\x79\x70\x65\x00\x64\
+  \\x65\x6c\x65\x67\x61\x74\x65\x54\x79\x70\x65\x00\x3c\x47\x65\x6e\x65\x72\x61\x74\
+  \\x65\x44\x65\x6c\x65\x67\x61\x74\x65\x43\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\
+  \\x53\x74\x75\x62\x3e\x62\x5f\x5f\x36\x00\x4c\x64\x61\x72\x67\x5f\x30\x00\x4c\x64\
+  \\x66\x74\x6e\x00\x3c\x3e\x63\x5f\x5f\x44\x69\x73\x70\x6c\x61\x79\x43\x6c\x61\x73\
+  \\x73\x61\x00\x66\x69\x65\x6c\x64\x00\x3c\x47\x65\x6e\x65\x72\x61\x74\x65\x46\x69\
+  \\x65\x6c\x64\x47\x65\x74\x53\x74\x75\x62\x3e\x62\x5f\x5f\x39\x00\x67\x65\x74\x5f\
+  \\x49\x73\x4c\x69\x74\x65\x72\x61\x6c\x00\x47\x65\x74\x52\x61\x77\x43\x6f\x6e\x73\
+  \\x74\x61\x6e\x74\x56\x61\x6c\x75\x65\x00\x4c\x64\x63\x5f\x49\x34\x00\x4c\x64\x73\
+  \\x66\x6c\x64\x00\x4c\x64\x66\x6c\x64\x00\x67\x65\x74\x5f\x46\x69\x65\x6c\x64\x54\
+  \\x79\x70\x65\x00\x3c\x3e\x63\x5f\x5f\x44\x69\x73\x70\x6c\x61\x79\x43\x6c\x61\x73\
+  \\x73\x64\x00\x3c\x47\x65\x6e\x65\x72\x61\x74\x65\x46\x69\x65\x6c\x64\x53\x65\x74\
+  \\x53\x74\x75\x62\x3e\x62\x5f\x5f\x63\x00\x53\x74\x73\x66\x6c\x64\x00\x53\x74\x66\
+  \\x6c\x64\x00\x56\x6f\x69\x64\x00\x3c\x3e\x63\x5f\x5f\x44\x69\x73\x70\x6c\x61\x79\
+  \\x43\x6c\x61\x73\x73\x31\x30\x00\x74\x79\x70\x65\x54\x6f\x42\x6f\x78\x00\x3c\x47\
+  \\x65\x6e\x65\x72\x61\x74\x65\x42\x6f\x78\x53\x74\x75\x62\x3e\x62\x5f\x5f\x66\x00\
+  \\x42\x6f\x78\x00\x74\x00\x67\x65\x74\x5f\x49\x73\x50\x72\x69\x6d\x69\x74\x69\x76\
+  \\x65\x00\x74\x79\x70\x65\x73\x00\x61\x72\x67\x75\x6d\x65\x6e\x74\x49\x6e\x64\x65\
+  \\x78\x00\x70\x61\x72\x61\x6d\x65\x74\x65\x72\x54\x79\x70\x65\x00\x76\x61\x6c\x75\
+  \\x65\x54\x79\x70\x65\x00\x55\x6e\x62\x6f\x78\x5f\x41\x6e\x79\x00\x73\x74\x61\x72\
+  \\x74\x69\x6e\x67\x41\x72\x67\x75\x6d\x65\x6e\x74\x00\x70\x61\x72\x61\x6d\x65\x74\
+  \\x65\x72\x49\x6e\x66\x6f\x73\x00\x49\x45\x6e\x75\x6d\x65\x72\x61\x74\x6f\x72\x60\
+  \\x31\x00\x47\x65\x74\x45\x6e\x75\x6d\x65\x72\x61\x74\x6f\x72\x00\x67\x65\x74\x5f\
+  \\x43\x75\x72\x72\x65\x6e\x74\x00\x53\x79\x73\x74\x65\x6d\x2e\x43\x6f\x6c\x6c\x65\
+  \\x63\x74\x69\x6f\x6e\x73\x00\x49\x45\x6e\x75\x6d\x65\x72\x61\x74\x6f\x72\x00\x4d\
+  \\x6f\x76\x65\x4e\x65\x78\x74\x00\x49\x44\x69\x73\x70\x6f\x73\x61\x62\x6c\x65\x00\
+  \\x44\x69\x73\x70\x6f\x73\x65\x00\x72\x65\x74\x75\x72\x6e\x50\x61\x72\x61\x6d\x65\
+  \\x74\x65\x72\x49\x6e\x66\x6f\x00\x6e\x61\x6d\x65\x00\x54\x79\x70\x65\x41\x74\x74\
+  \\x72\x69\x62\x75\x74\x65\x73\x00\x46\x69\x65\x6c\x64\x42\x75\x69\x6c\x64\x65\x72\
+  \\x00\x46\x69\x65\x6c\x64\x41\x74\x74\x72\x69\x62\x75\x74\x65\x73\x00\x44\x65\x66\
+  \\x69\x6e\x65\x46\x69\x65\x6c\x64\x00\x43\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72\
+  \\x42\x75\x69\x6c\x64\x65\x72\x00\x43\x61\x6c\x6c\x69\x6e\x67\x43\x6f\x6e\x76\x65\
+  \\x6e\x74\x69\x6f\x6e\x73\x00\x44\x65\x66\x69\x6e\x65\x43\x6f\x6e\x73\x74\x72\x75\
+  \\x63\x74\x6f\x72\x00\x4c\x64\x61\x72\x67\x5f\x31\x00\x4c\x64\x74\x6f\x6b\x65\x6e\
+  \\x00\x43\x61\x73\x74\x63\x6c\x61\x73\x73\x00\x4d\x65\x74\x68\x6f\x64\x49\x6d\x70\
+  \\x6c\x41\x74\x74\x72\x69\x62\x75\x74\x65\x73\x00\x53\x65\x74\x49\x6d\x70\x6c\x65\
+  \\x6d\x65\x6e\x74\x61\x74\x69\x6f\x6e\x46\x6c\x61\x67\x73\x00\x4c\x61\x62\x65\x6c\
+  \\x00\x44\x65\x66\x69\x6e\x65\x4c\x61\x62\x65\x6c\x00\x4c\x64\x63\x5f\x49\x34\x5f\
+  \\x30\x00\x42\x65\x71\x00\x4d\x61\x72\x6b\x4c\x61\x62\x65\x6c\x00\x55\x6e\x6d\x61\
+  \\x6e\x61\x67\x65\x64\x46\x75\x6e\x63\x74\x69\x6f\x6e\x50\x6f\x69\x6e\x74\x65\x72\
+  \\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x43\x61\x6c\x6c\x69\x6e\x67\x43\x6f\x6e\
+  \\x76\x65\x6e\x74\x69\x6f\x6e\x00\x6f\x62\x6a\x65\x63\x74\x00\x6d\x65\x74\x68\x6f\
+  \\x64\x00\x63\x61\x6c\x6c\x62\x61\x63\x6b\x00\x72\x65\x73\x75\x6c\x74\x00\x53\x74\
+  \\x72\x75\x63\x74\x4c\x61\x79\x6f\x75\x74\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\
+  \\x4c\x61\x79\x6f\x75\x74\x4b\x69\x6e\x64\x00\x72\x65\x74\x75\x72\x6e\x54\x79\x70\
+  \\x65\x00\x70\x61\x72\x61\x6d\x65\x74\x65\x72\x54\x79\x70\x65\x73\x00\x53\x79\x73\
+  \\x74\x65\x6d\x2e\x54\x65\x78\x74\x00\x53\x74\x72\x69\x6e\x67\x42\x75\x69\x6c\x64\
+  \\x65\x72\x00\x41\x70\x70\x65\x6e\x64\x00\x43\x75\x73\x74\x6f\x6d\x41\x74\x74\x72\
+  \\x69\x62\x75\x74\x65\x42\x75\x69\x6c\x64\x65\x72\x00\x53\x65\x74\x43\x75\x73\x74\
+  \\x6f\x6d\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x67\x65\x74\x5f\x48\x61\x73\x56\
+  \\x61\x6c\x75\x65\x00\x50\x61\x72\x61\x6d\x65\x74\x65\x72\x42\x75\x69\x6c\x64\x65\
+  \\x72\x00\x50\x61\x72\x61\x6d\x65\x74\x65\x72\x41\x74\x74\x72\x69\x62\x75\x74\x65\
+  \\x73\x00\x44\x65\x66\x69\x6e\x65\x50\x61\x72\x61\x6d\x65\x74\x65\x72\x00\x4d\x61\
+  \\x72\x73\x68\x61\x6c\x41\x73\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x67\x65\x74\
+  \\x5f\x56\x61\x6c\x75\x65\x00\x43\x6f\x6d\x70\x69\x6c\x65\x72\x47\x65\x6e\x65\x72\
+  \\x61\x74\x65\x64\x41\x74\x74\x72\x69\x62\x75\x74\x65\x00\x42\x69\x6e\x64\x69\x6e\
+  \\x67\x46\x6c\x61\x67\x73\x00\x73\x00\x47\x65\x74\x54\x79\x70\x65\x00\x3c\x53\x74\
+  \\x72\x69\x6e\x67\x54\x6f\x54\x79\x70\x65\x73\x3e\x62\x5f\x5f\x30\x00\x3c\x3e\x39\
+  \\x5f\x5f\x43\x61\x63\x68\x65\x64\x41\x6e\x6f\x6e\x79\x6d\x6f\x75\x73\x4d\x65\x74\
+  \\x68\x6f\x64\x44\x65\x6c\x65\x67\x61\x74\x65\x31\x00\x43\x68\x61\x72\x00\x53\x74\
+  \\x72\x69\x6e\x67\x53\x70\x6c\x69\x74\x4f\x70\x74\x69\x6f\x6e\x73\x00\x53\x70\x6c\
+  \\x69\x74\x00\x61\x00\x62\x00\x78\x00\x66\x00\x78\x73\x00\x3c\x4d\x61\x70\x50\x61\
+  \\x72\x61\x6d\x65\x74\x65\x72\x73\x54\x6f\x54\x79\x70\x65\x73\x3e\x62\x5f\x5f\x32\
+  \\x00\x3c\x3e\x39\x5f\x5f\x43\x61\x63\x68\x65\x64\x41\x6e\x6f\x6e\x79\x6d\x6f\x75\
+  \\x73\x4d\x65\x74\x68\x6f\x64\x44\x65\x6c\x65\x67\x61\x74\x65\x33\x00\x70\x00\x70\
+  \\x61\x72\x61\x6d\x65\x74\x65\x72\x73\x00\x4c\x64\x61\x72\x67\x5f\x32\x00\x4c\x64\
+  \\x61\x72\x67\x5f\x33\x00\x4c\x64\x61\x72\x67\x5f\x53\x00\x4c\x64\x61\x72\x67\x00\
+  \\x78\x31\x00\x00\x00\x1f\x44\x00\x79\x00\x6e\x00\x61\x00\x6d\x00\x69\x00\x63\x00\
+  \\x41\x00\x73\x00\x73\x00\x65\x00\x6d\x00\x62\x00\x6c\x00\x79\x00\x00\x1b\x44\x00\
+  \\x79\x00\x6e\x00\x61\x00\x6d\x00\x69\x00\x63\x00\x4d\x00\x6f\x00\x64\x00\x75\x00\
+  \\x6c\x00\x65\x00\x00\x17\x44\x00\x79\x00\x6e\x00\x61\x00\x6d\x00\x69\x00\x63\x00\
+  \\x2e\x00\x64\x00\x6c\x00\x6c\x00\x00\x0b\x53\x00\x74\x00\x75\x00\x62\x00\x73\x00\
+  \\x00\x25\x47\x00\x65\x00\x74\x00\x50\x00\x6f\x00\x69\x00\x6e\x00\x74\x00\x65\x00\
+  \\x72\x00\x54\x00\x6f\x00\x4d\x00\x65\x00\x74\x00\x68\x00\x6f\x00\x64\x00\x00\x23\
+  \\x4d\x00\x65\x00\x74\x00\x68\x00\x6f\x00\x64\x00\x20\x00\x6e\x00\x6f\x00\x74\x00\
+  \\x20\x00\x66\x00\x6f\x00\x75\x00\x6e\x00\x64\x00\x2e\x00\x00\x15\x6d\x00\x65\x00\
+  \\x74\x00\x68\x00\x6f\x00\x64\x00\x4e\x00\x61\x00\x6d\x00\x65\x00\x00\x33\x53\x00\
+  \\x61\x00\x76\x00\x69\x00\x6e\x00\x67\x00\x20\x00\x64\x00\x79\x00\x6e\x00\x61\x00\
+  \\x6d\x00\x69\x00\x63\x00\x20\x00\x61\x00\x73\x00\x73\x00\x65\x00\x6d\x00\x62\x00\
+  \\x6c\x00\x79\x00\x3a\x00\x20\x00\x00\x0b\x2e\x00\x63\x00\x74\x00\x6f\x00\x72\x00\
+  \\x00\x35\x4e\x00\x6f\x00\x20\x00\x6f\x00\x62\x00\x6a\x00\x65\x00\x63\x00\x74\x00\
+  \\x20\x00\x65\x00\x78\x00\x69\x00\x73\x00\x74\x00\x73\x00\x20\x00\x77\x00\x69\x00\
+  \\x74\x00\x68\x00\x20\x00\x69\x00\x64\x00\x3a\x00\x20\x00\x00\x65\x27\x00\x63\x00\
+  \\x6f\x00\x6e\x00\x27\x00\x20\x00\x63\x00\x61\x00\x6e\x00\x6e\x00\x6f\x00\x74\x00\
+  \\x20\x00\x62\x00\x65\x00\x20\x00\x6e\x00\x75\x00\x6c\x00\x6c\x00\x20\x00\x69\x00\
+  \\x66\x00\x20\x00\x63\x00\x72\x00\x65\x00\x61\x00\x74\x00\x69\x00\x6e\x00\x67\x00\
+  \\x20\x00\x61\x00\x20\x00\x72\x00\x65\x00\x66\x00\x65\x00\x72\x00\x65\x00\x6e\x00\
+  \\x63\x00\x65\x00\x20\x00\x74\x00\x79\x00\x70\x00\x65\x00\x2e\x00\x01\x07\x4e\x00\
+  \\x65\x00\x77\x00\x00\x03\x5f\x00\x00\x0d\x49\x00\x6e\x00\x76\x00\x6f\x00\x6b\x00\
+  \\x65\x00\x00\x17\x5f\x00\x66\x00\x69\x00\x65\x00\x6c\x00\x64\x00\x5f\x00\x67\x00\
+  \\x65\x00\x74\x00\x5f\x00\x00\x17\x5f\x00\x66\x00\x69\x00\x65\x00\x6c\x00\x64\x00\
+  \\x5f\x00\x73\x00\x65\x00\x74\x00\x5f\x00\x00\x09\x62\x00\x6f\x00\x78\x00\x5f\x00\
+  \\x00\x0f\x57\x00\x72\x00\x61\x00\x70\x00\x70\x00\x65\x00\x72\x00\x00\x1d\x5f\x00\
+  \\x74\x00\x68\x00\x75\x00\x6e\x00\x6b\x00\x44\x00\x65\x00\x6c\x00\x65\x00\x67\x00\
+  \\x61\x00\x74\x00\x65\x00\x00\x11\x46\x00\x69\x00\x6e\x00\x61\x00\x6c\x00\x69\x00\
+  \\x7a\x00\x65\x00\x00\x05\x54\x00\x6f\x00\x00\x11\x44\x00\x65\x00\x6c\x00\x65\x00\
+  \\x67\x00\x61\x00\x74\x00\x65\x00\x00\x23\x47\x00\x65\x00\x74\x00\x54\x00\x79\x00\
+  \\x70\x00\x65\x00\x46\x00\x72\x00\x6f\x00\x6d\x00\x48\x00\x61\x00\x6e\x00\x64\x00\
+  \\x6c\x00\x65\x00\x00\x3b\x47\x00\x65\x00\x74\x00\x44\x00\x65\x00\x6c\x00\x65\x00\
+  \\x67\x00\x61\x00\x74\x00\x65\x00\x46\x00\x6f\x00\x72\x00\x46\x00\x75\x00\x6e\x00\
+  \\x63\x00\x74\x00\x69\x00\x6f\x00\x6e\x00\x50\x00\x6f\x00\x69\x00\x6e\x00\x74\x00\
+  \\x65\x00\x72\x00\x00\x3b\x47\x00\x65\x00\x74\x00\x46\x00\x75\x00\x6e\x00\x63\x00\
+  \\x74\x00\x69\x00\x6f\x00\x6e\x00\x50\x00\x6f\x00\x69\x00\x6e\x00\x74\x00\x65\x00\
+  \\x72\x00\x46\x00\x6f\x00\x72\x00\x44\x00\x65\x00\x6c\x00\x65\x00\x67\x00\x61\x00\
+  \\x74\x00\x65\x00\x00\x25\x53\x00\x74\x00\x72\x00\x69\x00\x6e\x00\x67\x00\x54\x00\
+  \\x6f\x00\x48\x00\x47\x00\x6c\x00\x6f\x00\x62\x00\x61\x00\x6c\x00\x55\x00\x6e\x00\
+  \\x69\x00\x00\x27\x53\x00\x74\x00\x72\x00\x69\x00\x6e\x00\x67\x00\x54\x00\x6f\x00\
+  \\x48\x00\x47\x00\x6c\x00\x6f\x00\x62\x00\x61\x00\x6c\x00\x41\x00\x6e\x00\x73\x00\
+  \\x69\x00\x00\x23\x46\x00\x72\x00\x65\x00\x65\x00\x48\x00\x61\x00\x73\x00\x6b\x00\
+  \\x65\x00\x6c\x00\x6c\x00\x46\x00\x75\x00\x6e\x00\x50\x00\x74\x00\x72\x00\x00\x1d\
+  \\x52\x00\x65\x00\x67\x00\x69\x00\x73\x00\x74\x00\x65\x00\x72\x00\x4f\x00\x62\x00\
+  \\x6a\x00\x65\x00\x63\x00\x74\x00\x00\x13\x47\x00\x65\x00\x74\x00\x4f\x00\x62\x00\
+  \\x6a\x00\x65\x00\x63\x00\x74\x00\x00\x00\x00\x00\xa7\xb1\x8f\x02\x0b\xf8\x6c\x46\
+  \\x97\xa3\x4b\x79\x11\xde\xca\xdf\x00\x08\xb7\x7a\x5c\x56\x19\x34\xe0\x89\x03\x06\
+  \\x12\x11\x03\x06\x12\x15\x03\x06\x12\x19\x03\x00\x00\x01\x03\x00\x00\x18\x04\x00\
+  \\x01\x18\x0e\x04\x00\x01\x01\x18\x03\x06\x12\x14\x06\x00\x03\x18\x0e\x0e\x0e\x05\
+  \\x00\x02\x18\x0e\x0e\x07\x06\x15\x12\x1d\x02\x08\x1c\x02\x06\x08\x04\x00\x01\x08\
+  \\x1c\x04\x00\x01\x1c\x08\x03\x06\x12\x0c\x04\x00\x01\x01\x08\x08\x06\x15\x12\x1d\
+  \\x02\x18\x12\x21\x05\x00\x01\x18\x12\x21\x08\x00\x03\x18\x0e\x11\x10\x12\x18\x05\
+  \\x00\x01\x18\x12\x25\x05\x00\x01\x18\x12\x29\x05\x00\x01\x18\x12\x2d\x05\x00\x01\
+  \\x18\x12\x31\x05\x00\x01\x02\x12\x2d\x0a\x00\x01\x15\x11\x35\x01\x11\x39\x12\x2d\
+  \\x08\x00\x01\x1d\x12\x2d\x1d\x12\x2d\x06\x00\x01\x12\x2d\x12\x2d\x08\x00\x03\x01\
+  \\x12\x3d\x08\x12\x2d\x07\x00\x02\x01\x12\x3d\x12\x2d\x0c\x00\x03\x01\x12\x3d\x08\
+  \\x15\x12\x41\x01\x12\x45\x07\x00\x02\x01\x12\x3d\x12\x45\x08\x06\x15\x12\x1d\x02\
+  \\x0e\x12\x2d\x07\x00\x02\x12\x2d\x0e\x12\x2d\x03\x20\x00\x01\x05\x20\x02\x01\x1c\
+  \\x18\x04\x20\x01\x01\x08\x08\x20\x03\x12\x49\x08\x12\x4d\x1c\x05\x20\x01\x01\x12\
+  \\x49\x03\x06\x12\x2d\x04\x06\x1d\x12\x2d\x04\x20\x00\x12\x2d\x05\x20\x00\x1d\x12\
+  \\x2d\x08\x20\x02\x01\x12\x2d\x1d\x12\x2d\x03\x20\x00\x0e\x06\x00\x01\x11\x10\x12\
+  \\x2d\x05\x20\x01\x12\x2d\x0e\x04\x28\x00\x12\x2d\x05\x28\x00\x1d\x12\x2d\x04\x20\
+  \\x01\x01\x18\x08\x20\x03\x12\x49\x18\x12\x4d\x1c\x05\x20\x01\x01\x12\x3d\x09\x20\
+  \\x03\x12\x49\x12\x3d\x12\x4d\x1c\x03\x06\x12\x29\x03\x06\x12\x25\x03\x06\x12\x31\
+  \\x05\x00\x01\x12\x2d\x0e\x06\x00\x01\x1d\x12\x2d\x0e\x0c\x10\x01\x02\x1d\x1e\x00\
+  \\x1d\x1e\x00\x1d\x1e\x00\x0b\x10\x01\x02\x1d\x1e\x00\x1e\x00\x1d\x1e\x00\x11\x10\
+  \\x02\x02\x1d\x1e\x01\x15\x12\x24\x02\x1e\x00\x1e\x01\x1d\x1e\x00\x08\x00\x01\x1d\
+  \\x12\x2d\x1d\x12\x45\x06\x00\x02\x01\x12\x3d\x08\x06\x20\x01\x13\x01\x13\x00\x09\
+  \\x20\x03\x12\x49\x13\x00\x12\x4d\x1c\x06\x20\x01\x13\x01\x12\x49\x04\x20\x01\x01\
+  \\x0e\x06\x15\x12\x1d\x02\x08\x1c\x07\x15\x12\x1d\x02\x18\x12\x21\x07\x15\x12\x1d\
+  \\x02\x0e\x12\x2d\x04\x00\x00\x12\x75\x05\x20\x01\x08\x12\x7d\x05\x00\x00\x12\x80\
+  \\x85\x0a\x20\x02\x12\x11\x12\x80\x89\x11\x80\x8d\x06\x20\x02\x12\x15\x0e\x0e\x05\
+  \\x20\x01\x12\x19\x0e\x07\x20\x02\x01\x13\x00\x13\x01\x07\x00\x01\x12\x2d\x11\x80\
+  \\x95\x05\x20\x01\x12\x29\x0e\x05\x20\x02\x01\x0e\x0e\x04\x07\x01\x12\x29\x02\x06\
+  \\x18\x05\x00\x02\x02\x18\x18\x07\x00\x02\x12\x21\x18\x12\x2d\x04\x00\x01\x0e\x0e\
+  \\x05\x00\x02\x0e\x0e\x0e\x04\x00\x01\x01\x0e\x03\x07\x01\x0e\x05\x00\x02\x02\x0e\
+  \\x0e\x07\x20\x01\x12\x25\x1d\x12\x2d\x08\x20\x02\x12\x29\x0e\x1d\x12\x2d\x06\x07\
+  \\x02\x12\x25\x12\x29\x04\x07\x01\x12\x2d\x05\x20\x01\x12\x31\x0e\x04\x07\x01\x12\
+  \\x31\x05\x15\x11\x35\x01\x02\x04\x00\x01\x01\x1c\x0a\x07\x03\x02\x08\x15\x12\x1d\
+  \\x02\x08\x1c\x08\x20\x02\x02\x13\x00\x10\x13\x01\x05\x00\x02\x0e\x1c\x1c\x0a\x07\
+  \\x03\x1c\x1c\x15\x12\x1d\x02\x08\x1c\x05\x20\x01\x02\x13\x00\x08\x07\x01\x15\x12\
+  \\x1d\x02\x08\x1c\x0a\x07\x02\x18\x15\x12\x1d\x02\x18\x12\x21\x09\x07\x01\x15\x12\
+  \\x1d\x02\x18\x12\x21\x0e\x20\x04\x12\x80\xbd\x0e\x11\x80\xc1\x12\x2d\x1d\x12\x2d\
+  \\x04\x20\x00\x12\x3d\x0b\x20\x04\x01\x0e\x12\x2d\x1d\x12\x2d\x12\x2d\x06\x20\x01\
+  \\x12\x21\x12\x2d\x08\x07\x02\x12\x80\xbd\x12\x80\xc5\x07\x20\x01\x12\x80\xc9\x12\
+  \\x2d\x04\x06\x11\x80\xd1\x07\x20\x02\x01\x11\x80\xd1\x05\x08\x20\x02\x01\x11\x80\
+  \\xd1\x12\x2d\x06\x20\x01\x01\x11\x80\xd1\x05\x20\x00\x1d\x12\x45\x08\x20\x02\x01\
+  \\x11\x80\xd1\x12\x25\x03\x20\x00\x02\x06\x07\x02\x11\x10\x12\x28\x08\x20\x02\x01\
+  \\x11\x80\xd1\x12\x29\x04\x20\x00\x12\x45\x04\x0a\x01\x12\x2d\x06\x00\x03\x0e\x0e\
+  \\x0e\x0e\x08\x07\x03\x12\x2d\x11\x10\x12\x2c\x08\x07\x02\x1d\x12\x2d\x1d\x12\x2d\
+  \\x09\x07\x03\x11\x10\x12\x30\x1d\x12\x2d\x03\x20\x00\x1c\x07\x20\x02\x01\x11\x80\
+  \\xd1\x08\x08\x20\x02\x01\x11\x80\xd1\x12\x31\x03\x07\x01\x1c\x09\x07\x03\x11\x10\
+  \\x12\x34\x1d\x12\x2d\x0c\x07\x04\x11\x10\x12\x38\x1d\x12\x2d\x1d\x12\x2d\x09\x07\
+  \\x03\x11\x10\x12\x3c\x1d\x12\x2d\x06\x15\x11\x35\x01\x11\x39\x05\x20\x01\x01\x13\
+  \\x00\x08\x07\x01\x15\x11\x35\x01\x11\x39\x08\x15\x12\x24\x02\x12\x2d\x12\x2d\x06\
+  \\x0a\x02\x12\x2d\x12\x2d\x06\x15\x12\x41\x01\x12\x45\x09\x20\x00\x15\x12\x80\xe5\
+  \\x01\x13\x00\x07\x15\x12\x80\xe5\x01\x12\x45\x04\x20\x00\x13\x00\x0e\x07\x04\x08\
+  \\x12\x45\x12\x2d\x15\x12\x80\xe5\x01\x12\x45\x0e\x07\x04\x0e\x12\x2d\x12\x2d\x15\
+  \\x12\x1d\x02\x0e\x12\x2d\x08\x20\x02\x12\x19\x0e\x11\x80\xf1\x0b\x20\x03\x12\x80\
+  \\xf5\x0e\x12\x2d\x11\x80\xf9\x0e\x20\x03\x12\x80\xfd\x11\x80\xc1\x11\x81\x01\x1d\
+  \\x12\x2d\x09\x20\x02\x12\x80\xbd\x0e\x11\x80\xc1\x06\x20\x01\x01\x11\x81\x05\x05\
+  \\x20\x00\x11\x81\x09\x09\x20\x02\x01\x11\x80\xd1\x11\x81\x09\x06\x20\x01\x01\x11\
+  \\x81\x09\x23\x07\x0e\x11\x10\x12\x2d\x12\x19\x12\x80\xf5\x12\x80\xfd\x12\x3d\x12\
+  \\x80\xbd\x12\x3d\x11\x81\x09\x12\x80\xbd\x12\x3d\x08\x11\x10\x1d\x12\x2d\x06\x20\
+  \\x01\x01\x11\x81\x11\x08\x01\x00\x03\x00\x00\x00\x00\x00\x06\x20\x01\x01\x11\x81\
+  \\x19\x06\x20\x01\x12\x81\x1d\x0e\x0b\x07\x04\x12\x81\x1d\x12\x2d\x1d\x12\x2d\x08\
+  \\x0a\x20\x03\x12\x19\x0e\x11\x80\xf1\x12\x2d\x07\x20\x02\x01\x12\x25\x1d\x1c\x06\
+  \\x20\x01\x01\x12\x81\x21\x0a\x20\x03\x12\x81\x25\x08\x11\x81\x29\x0e\x21\x07\x0b\
+  \\x12\x19\x12\x80\xfd\x12\x80\xbd\x08\x15\x11\x35\x01\x11\x39\x12\x81\x25\x1d\x12\
+  \\x2d\x1d\x1c\x1d\x12\x2d\x1d\x12\x2d\x1d\x1c\x04\x01\x00\x00\x00\x08\x20\x02\x12\
+  \\x31\x0e\x11\x81\x35\x08\x20\x02\x12\x29\x0e\x11\x81\x35\x06\x00\x02\x12\x2d\x0e\
+  \\x02\x08\x06\x15\x12\x24\x02\x0e\x12\x2d\x07\x15\x12\x24\x02\x0e\x12\x2d\x09\x20\
+  \\x02\x1d\x0e\x1d\x03\x11\x81\x3d\x05\x0a\x02\x0e\x12\x2d\x04\x07\x01\x1d\x03\x02\
+  \\x1e\x00\x07\x07\x03\x1d\x1e\x00\x08\x08\x06\x07\x02\x1d\x1e\x00\x08\x02\x1e\x01\
+  \\x08\x15\x12\x24\x02\x1e\x00\x1e\x01\x06\x07\x02\x1d\x1e\x01\x08\x06\x00\x01\x12\
+  \\x2d\x12\x45\x09\x06\x15\x12\x24\x02\x12\x45\x12\x2d\x08\x15\x12\x24\x02\x12\x45\
+  \\x12\x2d\x06\x0a\x02\x12\x45\x12\x2d\x0c\x01\x00\x07\x31\x2e\x30\x2e\x30\x2e\x30\
+  \\x00\x00\x2c\x01\x00\x27\x43\x6f\x70\x79\x72\x69\x67\x68\x74\x20\xc2\xa9\x20\x32\
+  \\x30\x30\x37\x2d\x32\x30\x30\x38\x20\x41\x6e\x64\x72\x65\x77\x20\x41\x70\x70\x6c\
+  \\x65\x79\x61\x72\x64\x00\x00\x0a\x01\x00\x05\x53\x61\x6c\x73\x61\x00\x00\x1c\x01\
+  \\x00\x17\x2e\x4e\x45\x54\x20\x42\x72\x69\x64\x67\x65\x20\x66\x6f\x72\x20\x48\x61\
+  \\x73\x6b\x65\x6c\x6c\x00\x00\x08\x01\x00\x08\x00\x00\x00\x00\x00\x1e\x01\x00\x01\
+  \\x00\x54\x02\x16\x57\x72\x61\x70\x4e\x6f\x6e\x45\x78\x63\x65\x70\x74\x69\x6f\x6e\
+  \\x54\x68\x72\x6f\x77\x73\x01\x00\x10\x61\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x2e\x61\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x20\x61\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x5f\x43\x6f\x72\x44\x6c\x6c\x4d\x61\x69\x6e\x00\x6d\x73\
+  \\x63\x6f\x72\x65\x65\x2e\x64\x6c\x6c\x00\x00\x00\x00\x00\xff\x25\x00\x20\x40\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x01\x00\x10\x00\x00\x00\x18\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x30\x00\x00\x80\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x48\x00\x00\x00\
+  \\x58\x80\x00\x00\x04\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x03\x34\x00\
+  \\x00\x00\x56\x00\x53\x00\x5f\x00\x56\x00\x45\x00\x52\x00\x53\x00\x49\x00\x4f\x00\
+  \\x4e\x00\x5f\x00\x49\x00\x4e\x00\x46\x00\x4f\x00\x00\x00\x00\x00\xbd\x04\xef\xfe\
+  \\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\
+  \\x3f\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x44\x00\x00\x00\x01\x00\x56\x00\x61\x00\x72\x00\
+  \\x46\x00\x69\x00\x6c\x00\x65\x00\x49\x00\x6e\x00\x66\x00\x6f\x00\x00\x00\x00\x00\
+  \\x24\x00\x04\x00\x00\x00\x54\x00\x72\x00\x61\x00\x6e\x00\x73\x00\x6c\x00\x61\x00\
+  \\x74\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x00\x00\x00\x00\xb0\x04\x64\x02\x00\x00\
+  \\x01\x00\x53\x00\x74\x00\x72\x00\x69\x00\x6e\x00\x67\x00\x46\x00\x69\x00\x6c\x00\
+  \\x65\x00\x49\x00\x6e\x00\x66\x00\x6f\x00\x00\x00\x40\x02\x00\x00\x01\x00\x30\x00\
+  \\x30\x00\x30\x00\x30\x00\x30\x00\x34\x00\x62\x00\x30\x00\x00\x00\x48\x00\x18\x00\
+  \\x01\x00\x43\x00\x6f\x00\x6d\x00\x6d\x00\x65\x00\x6e\x00\x74\x00\x73\x00\x00\x00\
+  \\x2e\x00\x4e\x00\x45\x00\x54\x00\x20\x00\x42\x00\x72\x00\x69\x00\x64\x00\x67\x00\
+  \\x65\x00\x20\x00\x66\x00\x6f\x00\x72\x00\x20\x00\x48\x00\x61\x00\x73\x00\x6b\x00\
+  \\x65\x00\x6c\x00\x6c\x00\x00\x00\x34\x00\x06\x00\x01\x00\x46\x00\x69\x00\x6c\x00\
+  \\x65\x00\x44\x00\x65\x00\x73\x00\x63\x00\x72\x00\x69\x00\x70\x00\x74\x00\x69\x00\
+  \\x6f\x00\x6e\x00\x00\x00\x00\x00\x53\x00\x61\x00\x6c\x00\x73\x00\x61\x00\x00\x00\
+  \\x30\x00\x08\x00\x01\x00\x46\x00\x69\x00\x6c\x00\x65\x00\x56\x00\x65\x00\x72\x00\
+  \\x73\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x00\x00\x31\x00\x2e\x00\x30\x00\x2e\x00\
+  \\x30\x00\x2e\x00\x30\x00\x00\x00\x34\x00\x0a\x00\x01\x00\x49\x00\x6e\x00\x74\x00\
+  \\x65\x00\x72\x00\x6e\x00\x61\x00\x6c\x00\x4e\x00\x61\x00\x6d\x00\x65\x00\x00\x00\
+  \\x53\x00\x61\x00\x6c\x00\x73\x00\x61\x00\x2e\x00\x64\x00\x6c\x00\x6c\x00\x00\x00\
+  \\x74\x00\x27\x00\x01\x00\x4c\x00\x65\x00\x67\x00\x61\x00\x6c\x00\x43\x00\x6f\x00\
+  \\x70\x00\x79\x00\x72\x00\x69\x00\x67\x00\x68\x00\x74\x00\x00\x00\x43\x00\x6f\x00\
+  \\x70\x00\x79\x00\x72\x00\x69\x00\x67\x00\x68\x00\x74\x00\x20\x00\xa9\x00\x20\x00\
+  \\x32\x00\x30\x00\x30\x00\x37\x00\x2d\x00\x32\x00\x30\x00\x30\x00\x38\x00\x20\x00\
+  \\x41\x00\x6e\x00\x64\x00\x72\x00\x65\x00\x77\x00\x20\x00\x41\x00\x70\x00\x70\x00\
+  \\x6c\x00\x65\x00\x79\x00\x61\x00\x72\x00\x64\x00\x00\x00\x00\x00\x3c\x00\x0a\x00\
+  \\x01\x00\x4f\x00\x72\x00\x69\x00\x67\x00\x69\x00\x6e\x00\x61\x00\x6c\x00\x46\x00\
+  \\x69\x00\x6c\x00\x65\x00\x6e\x00\x61\x00\x6d\x00\x65\x00\x00\x00\x53\x00\x61\x00\
+  \\x6c\x00\x73\x00\x61\x00\x2e\x00\x64\x00\x6c\x00\x6c\x00\x00\x00\x2c\x00\x06\x00\
+  \\x01\x00\x50\x00\x72\x00\x6f\x00\x64\x00\x75\x00\x63\x00\x74\x00\x4e\x00\x61\x00\
+  \\x6d\x00\x65\x00\x00\x00\x00\x00\x53\x00\x61\x00\x6c\x00\x73\x00\x61\x00\x00\x00\
+  \\x34\x00\x08\x00\x01\x00\x50\x00\x72\x00\x6f\x00\x64\x00\x75\x00\x63\x00\x74\x00\
+  \\x56\x00\x65\x00\x72\x00\x73\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x31\x00\x2e\x00\
+  \\x30\x00\x2e\x00\x30\x00\x2e\x00\x30\x00\x00\x00\x38\x00\x08\x00\x01\x00\x41\x00\
+  \\x73\x00\x73\x00\x65\x00\x6d\x00\x62\x00\x6c\x00\x79\x00\x20\x00\x56\x00\x65\x00\
+  \\x72\x00\x73\x00\x69\x00\x6f\x00\x6e\x00\x00\x00\x31\x00\x2e\x00\x30\x00\x2e\x00\
+  \\x30\x00\x2e\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60\x00\x00\x0c\x00\x00\x00\
+  \\x40\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+  \\x00\x00\x00\x00"
diff --git a/Foreign/Salsa/Resolver.hs b/Foreign/Salsa/Resolver.hs
new file mode 100644
--- /dev/null
+++ b/Foreign/Salsa/Resolver.hs
@@ -0,0 +1,261 @@
+{-# LANGUAGE TypeFamilies, MultiParamTypeClasses, EmptyDataDecls, TypeOperators #-}
+{-# OPTIONS_GHC -fallow-undecidable-instances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Foreign.Salsa.Resolver
+-- Copyright   : (c) 2007-2008 Andrew Appleyard
+-- Licence     : BSD-style (see LICENSE)
+-- 
+-- Contains a type-level implementation of the C# function member overload
+-- resolution algorithm, as described in the \"C# Language Specification\"
+-- (particularly, section 7.4.2).
+--
+-----------------------------------------------------------------------------
+module Foreign.Salsa.Resolver where
+
+import Foreign.Salsa.Common
+import Foreign.Salsa.TypePrelude
+
+--
+-- Basic predicates
+--
+
+type family    IsPrim t
+type instance  IsPrim Int32      = TTrue
+type instance  IsPrim String     = TTrue
+type instance  IsPrim Bool       = TTrue
+type instance  IsPrim Double     = TTrue
+type instance  IsPrim (Obj t)    = TFalse
+
+type family    IsRef t
+type instance  IsRef t = TNot (IsPrim t)
+-- FIXME: This definition of IsRef is incorrect.  String is a reference
+--        type (in .NET) but it is also a primitive bridge type.
+
+--
+-- Operations on the encoded (Gödel) representations of .NET types:
+--
+
+-- | 'TyCode' maps labels representing .NET types to a type-level list of hexadecimal
+--   values (similar to Gödel numbering) which can (then) be compared for equality.
+--   This avoids having to define a large type function for comparing every pair
+--   of labels used to represent .NET types.
+type family TyCode t
+
+type instance TyCode Int32              = D0 ::: TNil
+type instance TyCode String             = D1 ::: TNil
+type instance TyCode Bool               = D2 ::: TNil
+type instance TyCode Double             = D3 ::: TNil
+type instance TyCode (Obj Null)         = D4 ::: TNil
+type instance TyCode (Maybe Bool)       = D5 ::: TNil -- Temporary HACK
+
+
+type family FromTyCode t
+type instance FromTyCode (D0 ::: TNil) = Int32
+type instance FromTyCode (D1 ::: TNil) = String
+type instance FromTyCode (D2 ::: TNil) = Bool
+type instance FromTyCode (D3 ::: TNil) = Double
+type instance FromTyCode (D4 ::: TNil) = Obj Null
+type instance FromTyCode (D5 ::: TNil) = Maybe Bool
+
+
+-- | 'TyEq t1 t2' is true iff the types @t1@ and @t2@ are the same .NET type
+--   (as indicated by their code).
+type family TyEq t1 t2
+type instance TyEq t1 t2 = DigitsEq (TyCode t1) (TyCode t2)
+
+
+-- | 'MemberEq m n' is true iff the members 'm' and 'n' have the same types.
+type family MemberEq m n
+type instance MemberEq TNil       TNil       = TTrue
+type instance MemberEq TNil       (n ::: ns) = TFalse
+type instance MemberEq (m ::: ms) TNil       = TFalse
+type instance MemberEq (m ::: ms) (n ::: ns) = TAnd (TyEq m n) (MemberEq ms ns)
+
+-- | @'TyElem' t ts@ is true iff the type @t@ is present in the list @ts@
+--   (containing coded type representations).
+type family    TyElem t1 ts
+type instance  TyElem t1 TNil        = TFalse
+type instance  TyElem t1 (t ::: ts)  = TOr (TyEq t1 t) (TyElem t1 ts)
+
+--
+-- Overload resolution algorithm:
+--
+
+-- | @'ResolveMember' ms as@ returns the best applicable function member from @ms@
+--   with respect to the argument list @as@ (if there is exactly one such member)
+--   (ref 7.4.2).
+--
+--     resolveMember :: [Member] -> [Type] -> Member
+--     resolveMember ms as =
+--         case (filterBestMembers as applicables applicables) of
+--             [m] -> m
+--             _   -> error "Ambiguous or no match"
+--         where applicables = filterApplicables as ms
+--
+type family ResolveMember as ms
+type instance ResolveMember as ms = ResolveMember' as (FilterApp as ms)
+-- was: FromSingleton (Error NoMatch) (FilterBestMembers as (FilterApp as ms) (FilterApp as ms))
+
+type family ResolveMember' as fa
+type instance ResolveMember' as fa = FromSingleton (Error NoMatch) (FilterBestMembers as fa fa)
+
+
+data Error x
+data NoMatch
+
+
+-- | @'FilterBestMembers' as ms ms@ returns the list of members from @ms@ that are
+--   better than all the other members in @ms@ (with respect to the argument list
+--   @as@). 
+--
+--     filterBestMembers :: [Type] -> [Member] -> [Member] -> [Member]
+--     filterBestMembers as ms ns = filter (isBestMember as ms) ns
+--
+type family FilterBestMembers as ms ns
+type instance FilterBestMembers as ms TNil       = TNil
+type instance FilterBestMembers as ms (n ::: ns) = FilterBestMembers' as ms n (FilterBestMembers as ms ns)
+-- was: If (IsBestMember as ms n) (n ::: (FilterBestMembers as ms ns))
+--                                (FilterBestMembers as ms ns)
+
+type family FilterBestMembers' as ms n fbms
+type instance FilterBestMembers' as ms n fbms = If (IsBestMember as ms n) (n ::: fbms) fbms
+
+
+-- | @'IsBestMember' as ms n@ is true iff the member @n@ is better than all
+--   the (other) members in @ms@ with respect to the argument list @as@. 
+--
+--     isBestMember :: [Type] -> [Member] -> Member -> Bool
+--     isBestMember _  []     _ = True
+--     isBestMember as (m:ms) n
+--         | m /= n    = isBetterMember as n m && isBestMember as ms n
+--         | otherwise = isBestMember as ms n -- skip members equal to 'n'
+--
+type family IsBestMember as ms n
+type instance IsBestMember as TNil       n = TTrue
+type instance IsBestMember as (m ::: ms) n =
+    If (MemberEq m n) (IsBestMember as ms n)
+                      (TAnd (IsBetterMember as n m) (IsBestMember as ms n))
+
+
+-- | @'FilterApp' as ms@ returns the list of members from @ms@ that are
+--   applicable with respect to the argument list @as@.
+type family    FilterApp  as  ms
+type instance  FilterApp  as  TNil        = TNil
+type instance  FilterApp  as  (m ::: ms)  = FilterApp' as m (FilterApp as ms)
+-- was: If (IsApp as m) (m ::: FilterApp as ms)
+--                      (FilterApp as ms)
+
+-- Note: use of FilterApp' increases compilation speed by a factor of 10 (!)
+type family    FilterApp' as m fas
+type instance  FilterApp' as m fas = If (IsApp as m) (m ::: fas) fas
+
+
+-- | @'IsApp' as ps@ is true iff the function member defined by the 
+--   parameters @ps@ is applicable with respect to the argument list @as@
+--   (ref 7.4.2.1).  This means they of the same length and an implicit
+--   conversion exists from the argument type to the corresponding
+--   parameter on the function member.
+type family    IsApp  as          ps
+type instance  IsApp  TNil        TNil       = TTrue
+type instance  IsApp  TNil        (p ::: ps) = TFalse -- different lengths
+type instance  IsApp  (a ::: as)  TNil       = TFalse -- different lengths
+type instance  IsApp  (a ::: as)  (p ::: ps) = TAnd (ConvertsTo a p) (IsApp as ps)
+
+
+-- | @'IsBetterMember' as ps qs@ returns true iff the function member defined by the
+--   parameters @ps@ is better than that given by parameters @qs@ given the list of
+--   argument types @as@ (ref 7.4.2.2).
+--
+--     isBetterMember :: [Type] -> Member -> Member -> Bool
+--     isBetterMember as ps qs = someBetter as ps qs && not (someBetter as qs ps)
+--
+type family IsBetterMember as ps qs
+type instance IsBetterMember as ps qs =
+    TAnd (AnyBetterConv as ps qs) 
+         (TNot (AnyBetterConv as qs ps))
+
+
+type family    AnyBetterConv  as          ss          ts
+type instance  AnyBetterConv  TNil        TNil        TNil        = TFalse
+type instance  AnyBetterConv  (a ::: as)  (s ::: ss)  (t ::: ts)  =
+    TOr (IsBetterConv a s t) (AnyBetterConv as ss ts)
+
+
+type family    IsBetterConv t t1 t2
+type instance  IsBetterConv t t1 t2 =
+    TOr  (TAnd (TyEq t t1) (TNot (TyEq t t2)))
+         (TAnd (ConvertsTo t1 t2) (TNot (ConvertsTo t2 t1)))
+
+--
+-- Original:
+--
+-- type instance  ConvertsTo t1 t2 =
+--     (TOr  (TyEq t1 t2)
+--     (TOr  (TAnd (IsPrim t1)           (TyEq t2 (Obj Object_)))
+--     (TOr  (TAnd (TyEq t1 Int32)       (TyEq t2 Double))
+--     (TOr  (TAnd (TyEq t1 (Obj Null))  (IsRef t2))
+--           (TAnd (TAnd (IsRef t1) (IsRef t2))
+--                 (IsSubtypeOf t1 t2))))))
+--
+
+-- | @'ConvertsTo' s t@ returns true iff there is an implicit conversion from @s@
+--   to @t@ (ref 6.1).
+type family    ConvertsTo t1 t2
+type instance  ConvertsTo t1 t2 =
+    (TOr  (TyEq t1 t2)
+    (TOr  (TAnd (IsPrim t1)           (TyEq t2 (Obj Object_)))
+    (TOr  (TAnd (TyEq t1 Int32)       (TyEq t2 Double))
+    (TOr  (TAnd (TyEq t1 (Obj Null))  (IsRef t2))
+    (TOr  (TAnd (TAnd (IsArr t1) (IsArr t2))
+                (IsSubtypeOf' (ArrElemTy t1) (ArrElemTy t2)))
+          (TAnd (TAnd (IsRef t1) (IsRef t2))
+                (IsSubtypeOf t1 t2)))))))
+
+
+--    (TOr5 (TyEq t1 t2)
+--          (TAnd (IsPrim t1)           (TyEq t2 (Obj Object_)))
+--          (TAnd (TyEq t1 Int32)       (TyEq t2 Double))
+--          (TAnd (TyEq t1 (Obj Null))  (IsRef t2))
+--          (TAnd3 (IsRef t1) (IsRef t2) (IsSubtypeOf t1 t2)))
+-- Note: using TOr5 instead of a nested set of TOr's only gives a small performance improvement.
+
+
+type family    IsSubtypeOf t1 t2
+type instance  IsSubtypeOf t1 t2  = 
+    TOr (TyEq t1 t2)
+        (TyElem t2 (SupertypesOf t1))
+
+type family    IsArr t
+type instance  IsArr t = TAnd (TNot (TyEq t (Obj Array_)))
+                              (IsSubtypeOf t (Obj Array_))
+
+type family   ArrElemTy t
+type instance ArrElemTy t =
+    ArrElemTy' (TyCode t)
+
+type family   ArrElemTy' tc
+type instance ArrElemTy' (D0 ::: DF ::: tc) = tc
+type family    IsSubtypeOf' t1 t2
+type instance  IsSubtypeOf' t1 TNil = TFalse -- we need this so that we can short-circuit evaluation
+type instance  IsSubtypeOf' t1 (t2 ::: t2s) = 
+    TOr (TyEq' t1 (t2 ::: t2s))
+        (TyElem' (t2 ::: t2s) (SupertypesOf (FromTyCode t1)))
+
+type family   TyEq' t1 t2
+type instance TyEq' t1 t2 = DigitsEq t1 t2
+
+type family    TyElem' t1 ts
+type instance  TyElem' t1 TNil        = TFalse
+type instance  TyElem' t1 (t ::: ts)  = TOr (TyEq' t1 (TyCode t)) (TyElem' t1 ts) -- UGLY!
+
+-- | @'SupertypesOf' t@ is the list of supertypes of @t@.
+type family SupertypesOf t
+
+type instance SupertypesOf String          = TNil
+type instance SupertypesOf Int32           = TNil
+type instance SupertypesOf Bool            = TNil
+type instance SupertypesOf Double          = TNil
+type instance SupertypesOf (Obj Null)      = TNil
+
+-- vim:set sw=4 ts=4 expandtab:
diff --git a/Foreign/Salsa/TypePrelude.hs b/Foreign/Salsa/TypePrelude.hs
new file mode 100644
--- /dev/null
+++ b/Foreign/Salsa/TypePrelude.hs
@@ -0,0 +1,364 @@
+{-# LANGUAGE TypeFamilies, TypeOperators, EmptyDataDecls #-}
+{-# OPTIONS_GHC -fallow-undecidable-instances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Foreign.Salsa.TypePrelude
+-- Copyright   : (c) 2007-2008 Andrew Appleyard
+-- Licence     : BSD-style (see LICENSE)
+-- 
+-- Type-level implementations of some standard boolean and list functions.
+-- Including short-circuited 'and' and 'or' logic functions.
+--
+-----------------------------------------------------------------------------
+module Foreign.Salsa.TypePrelude where
+
+--
+-- Type-level booleans and boolean operations:
+--
+
+data TTrue  = TTrue
+data TFalse = TFalse
+
+type family TOr x y
+type instance TOr TTrue  x  = TTrue
+type instance TOr TFalse x  = x
+
+type family TAnd x y
+type instance TAnd TFalse x  = TFalse
+type instance TAnd TTrue  x  = x
+
+type family TNot x
+type instance TNot TTrue  = TFalse
+type instance TNot TFalse = TTrue
+
+type family If c a b
+type instance If TTrue  a b = a
+type instance If TFalse a b = b
+
+--type family TAnd3 x y z
+--type instance TAnd3 TFalse y      z = TFalse
+--type instance TAnd3 TTrue  TFalse z = TFalse
+--type instance TAnd3 TTrue  TTrue  z = z
+
+--type family TOr5 a b c d e
+--type instance TOr5 TTrue  b      c      d      e = TTrue
+--type instance TOr5 TFalse TTrue  c      d      e = TTrue
+--type instance TOr5 TFalse TFalse TTrue  d      e = TTrue
+--type instance TOr5 TFalse TFalse TFalse TTrue  e = TTrue
+--type instance TOr5 TFalse TFalse TFalse TFalse e = e
+
+--
+-- Type-level lists and associated operations:
+--
+
+data TNil
+data x ::: xs -- = x ::: xs
+infixr 5 :::
+
+type family    BoolEq x       y
+type instance  BoolEq TTrue   TTrue   = TTrue
+type instance  BoolEq TFalse  TFalse  = TTrue
+type instance  BoolEq TFalse  TTrue   = TFalse
+type instance  BoolEq TTrue   TFalse  = TFalse
+
+-- | 'ListEq xs ys' is true if the given type-level boolean lists contain 
+--   the same boolean values, and false otherwise.
+type family    ListEq xs          ys
+type instance  ListEq TNil        TNil        = TTrue
+type instance  ListEq (x ::: xs)  TNil        = TFalse
+type instance  ListEq TNil        (x ::: xs)  = TFalse
+type instance  ListEq (x ::: xs)  (y ::: ys)  = TAnd (BoolEq x y) (ListEq xs ys)
+
+-- | @'FromSingleton' xs def@ returns the only element of the list @xs@ (if it is a
+--   single element list), otherwise it returns the default value @def@.
+type family FromSingleton def xs
+type instance FromSingleton def TNil            = def
+type instance FromSingleton def (x ::: TNil)    = x
+type instance FromSingleton def (x ::: y ::: z) = def
+
+-- 
+-- Type-level base-16 digits and equality:
+--
+
+data D0 = D0
+data D1 = D1
+data D2 = D2
+data D3 = D3
+data D4 = D4
+data D5 = D5
+data D6 = D6
+data D7 = D7
+data D8 = D8
+data D9 = D9
+data DA = DA
+data DB = DB
+data DC = DC
+data DD = DD
+data DE = DE
+data DF = DF
+
+type family    DigitEq x  y
+type instance  DigitEq D0 D0 = TTrue
+type instance  DigitEq D1 D0 = TFalse
+type instance  DigitEq D2 D0 = TFalse
+type instance  DigitEq D3 D0 = TFalse
+type instance  DigitEq D4 D0 = TFalse
+type instance  DigitEq D5 D0 = TFalse
+type instance  DigitEq D6 D0 = TFalse
+type instance  DigitEq D7 D0 = TFalse
+type instance  DigitEq D8 D0 = TFalse
+type instance  DigitEq D9 D0 = TFalse
+type instance  DigitEq DA D0 = TFalse
+type instance  DigitEq DB D0 = TFalse
+type instance  DigitEq DC D0 = TFalse
+type instance  DigitEq DD D0 = TFalse
+type instance  DigitEq DE D0 = TFalse
+type instance  DigitEq DF D0 = TFalse
+type instance  DigitEq D0 D1 = TFalse
+type instance  DigitEq D1 D1 = TTrue
+type instance  DigitEq D2 D1 = TFalse
+type instance  DigitEq D3 D1 = TFalse
+type instance  DigitEq D4 D1 = TFalse
+type instance  DigitEq D5 D1 = TFalse
+type instance  DigitEq D6 D1 = TFalse
+type instance  DigitEq D7 D1 = TFalse
+type instance  DigitEq D8 D1 = TFalse
+type instance  DigitEq D9 D1 = TFalse
+type instance  DigitEq DA D1 = TFalse
+type instance  DigitEq DB D1 = TFalse
+type instance  DigitEq DC D1 = TFalse
+type instance  DigitEq DD D1 = TFalse
+type instance  DigitEq DE D1 = TFalse
+type instance  DigitEq DF D1 = TFalse
+type instance  DigitEq D0 D2 = TFalse
+type instance  DigitEq D1 D2 = TFalse
+type instance  DigitEq D2 D2 = TTrue
+type instance  DigitEq D3 D2 = TFalse
+type instance  DigitEq D4 D2 = TFalse
+type instance  DigitEq D5 D2 = TFalse
+type instance  DigitEq D6 D2 = TFalse
+type instance  DigitEq D7 D2 = TFalse
+type instance  DigitEq D8 D2 = TFalse
+type instance  DigitEq D9 D2 = TFalse
+type instance  DigitEq DA D2 = TFalse
+type instance  DigitEq DB D2 = TFalse
+type instance  DigitEq DC D2 = TFalse
+type instance  DigitEq DD D2 = TFalse
+type instance  DigitEq DE D2 = TFalse
+type instance  DigitEq DF D2 = TFalse
+type instance  DigitEq D0 D3 = TFalse
+type instance  DigitEq D1 D3 = TFalse
+type instance  DigitEq D2 D3 = TFalse
+type instance  DigitEq D3 D3 = TTrue
+type instance  DigitEq D4 D3 = TFalse
+type instance  DigitEq D5 D3 = TFalse
+type instance  DigitEq D6 D3 = TFalse
+type instance  DigitEq D7 D3 = TFalse
+type instance  DigitEq D8 D3 = TFalse
+type instance  DigitEq D9 D3 = TFalse
+type instance  DigitEq DA D3 = TFalse
+type instance  DigitEq DB D3 = TFalse
+type instance  DigitEq DC D3 = TFalse
+type instance  DigitEq DD D3 = TFalse
+type instance  DigitEq DE D3 = TFalse
+type instance  DigitEq DF D3 = TFalse
+type instance  DigitEq D0 D4 = TFalse
+type instance  DigitEq D1 D4 = TFalse
+type instance  DigitEq D2 D4 = TFalse
+type instance  DigitEq D3 D4 = TFalse
+type instance  DigitEq D4 D4 = TTrue
+type instance  DigitEq D5 D4 = TFalse
+type instance  DigitEq D6 D4 = TFalse
+type instance  DigitEq D7 D4 = TFalse
+type instance  DigitEq D8 D4 = TFalse
+type instance  DigitEq D9 D4 = TFalse
+type instance  DigitEq DA D4 = TFalse
+type instance  DigitEq DB D4 = TFalse
+type instance  DigitEq DC D4 = TFalse
+type instance  DigitEq DD D4 = TFalse
+type instance  DigitEq DE D4 = TFalse
+type instance  DigitEq DF D4 = TFalse
+type instance  DigitEq D0 D5 = TFalse
+type instance  DigitEq D1 D5 = TFalse
+type instance  DigitEq D2 D5 = TFalse
+type instance  DigitEq D3 D5 = TFalse
+type instance  DigitEq D4 D5 = TFalse
+type instance  DigitEq D5 D5 = TTrue
+type instance  DigitEq D6 D5 = TFalse
+type instance  DigitEq D7 D5 = TFalse
+type instance  DigitEq D8 D5 = TFalse
+type instance  DigitEq D9 D5 = TFalse
+type instance  DigitEq DA D5 = TFalse
+type instance  DigitEq DB D5 = TFalse
+type instance  DigitEq DC D5 = TFalse
+type instance  DigitEq DD D5 = TFalse
+type instance  DigitEq DE D5 = TFalse
+type instance  DigitEq DF D5 = TFalse
+type instance  DigitEq D0 D6 = TFalse
+type instance  DigitEq D1 D6 = TFalse
+type instance  DigitEq D2 D6 = TFalse
+type instance  DigitEq D3 D6 = TFalse
+type instance  DigitEq D4 D6 = TFalse
+type instance  DigitEq D5 D6 = TFalse
+type instance  DigitEq D6 D6 = TTrue
+type instance  DigitEq D7 D6 = TFalse
+type instance  DigitEq D8 D6 = TFalse
+type instance  DigitEq D9 D6 = TFalse
+type instance  DigitEq DA D6 = TFalse
+type instance  DigitEq DB D6 = TFalse
+type instance  DigitEq DC D6 = TFalse
+type instance  DigitEq DD D6 = TFalse
+type instance  DigitEq DE D6 = TFalse
+type instance  DigitEq DF D6 = TFalse
+type instance  DigitEq D0 D7 = TFalse
+type instance  DigitEq D1 D7 = TFalse
+type instance  DigitEq D2 D7 = TFalse
+type instance  DigitEq D3 D7 = TFalse
+type instance  DigitEq D4 D7 = TFalse
+type instance  DigitEq D5 D7 = TFalse
+type instance  DigitEq D6 D7 = TFalse
+type instance  DigitEq D7 D7 = TTrue
+type instance  DigitEq D8 D7 = TFalse
+type instance  DigitEq D9 D7 = TFalse
+type instance  DigitEq DA D7 = TFalse
+type instance  DigitEq DB D7 = TFalse
+type instance  DigitEq DC D7 = TFalse
+type instance  DigitEq DD D7 = TFalse
+type instance  DigitEq DE D7 = TFalse
+type instance  DigitEq DF D7 = TFalse
+type instance  DigitEq D0 D8 = TFalse
+type instance  DigitEq D1 D8 = TFalse
+type instance  DigitEq D2 D8 = TFalse
+type instance  DigitEq D3 D8 = TFalse
+type instance  DigitEq D4 D8 = TFalse
+type instance  DigitEq D5 D8 = TFalse
+type instance  DigitEq D6 D8 = TFalse
+type instance  DigitEq D7 D8 = TFalse
+type instance  DigitEq D8 D8 = TTrue
+type instance  DigitEq D9 D8 = TFalse
+type instance  DigitEq DA D8 = TFalse
+type instance  DigitEq DB D8 = TFalse
+type instance  DigitEq DC D8 = TFalse
+type instance  DigitEq DD D8 = TFalse
+type instance  DigitEq DE D8 = TFalse
+type instance  DigitEq DF D8 = TFalse
+type instance  DigitEq D0 D9 = TFalse
+type instance  DigitEq D1 D9 = TFalse
+type instance  DigitEq D2 D9 = TFalse
+type instance  DigitEq D3 D9 = TFalse
+type instance  DigitEq D4 D9 = TFalse
+type instance  DigitEq D5 D9 = TFalse
+type instance  DigitEq D6 D9 = TFalse
+type instance  DigitEq D7 D9 = TFalse
+type instance  DigitEq D8 D9 = TFalse
+type instance  DigitEq D9 D9 = TTrue
+type instance  DigitEq DA D9 = TFalse
+type instance  DigitEq DB D9 = TFalse
+type instance  DigitEq DC D9 = TFalse
+type instance  DigitEq DD D9 = TFalse
+type instance  DigitEq DE D9 = TFalse
+type instance  DigitEq DF D9 = TFalse
+type instance  DigitEq D0 DA = TFalse
+type instance  DigitEq D1 DA = TFalse
+type instance  DigitEq D2 DA = TFalse
+type instance  DigitEq D3 DA = TFalse
+type instance  DigitEq D4 DA = TFalse
+type instance  DigitEq D5 DA = TFalse
+type instance  DigitEq D6 DA = TFalse
+type instance  DigitEq D7 DA = TFalse
+type instance  DigitEq D8 DA = TFalse
+type instance  DigitEq D9 DA = TFalse
+type instance  DigitEq DA DA = TTrue
+type instance  DigitEq DB DA = TFalse
+type instance  DigitEq DC DA = TFalse
+type instance  DigitEq DD DA = TFalse
+type instance  DigitEq DE DA = TFalse
+type instance  DigitEq DF DA = TFalse
+type instance  DigitEq D0 DB = TFalse
+type instance  DigitEq D1 DB = TFalse
+type instance  DigitEq D2 DB = TFalse
+type instance  DigitEq D3 DB = TFalse
+type instance  DigitEq D4 DB = TFalse
+type instance  DigitEq D5 DB = TFalse
+type instance  DigitEq D6 DB = TFalse
+type instance  DigitEq D7 DB = TFalse
+type instance  DigitEq D8 DB = TFalse
+type instance  DigitEq D9 DB = TFalse
+type instance  DigitEq DA DB = TFalse
+type instance  DigitEq DB DB = TTrue
+type instance  DigitEq DC DB = TFalse
+type instance  DigitEq DD DB = TFalse
+type instance  DigitEq DE DB = TFalse
+type instance  DigitEq DF DB = TFalse
+type instance  DigitEq D0 DC = TFalse
+type instance  DigitEq D1 DC = TFalse
+type instance  DigitEq D2 DC = TFalse
+type instance  DigitEq D3 DC = TFalse
+type instance  DigitEq D4 DC = TFalse
+type instance  DigitEq D5 DC = TFalse
+type instance  DigitEq D6 DC = TFalse
+type instance  DigitEq D7 DC = TFalse
+type instance  DigitEq D8 DC = TFalse
+type instance  DigitEq D9 DC = TFalse
+type instance  DigitEq DA DC = TFalse
+type instance  DigitEq DB DC = TFalse
+type instance  DigitEq DC DC = TTrue
+type instance  DigitEq DD DC = TFalse
+type instance  DigitEq DE DC = TFalse
+type instance  DigitEq DF DC = TFalse
+type instance  DigitEq D0 DD = TFalse
+type instance  DigitEq D1 DD = TFalse
+type instance  DigitEq D2 DD = TFalse
+type instance  DigitEq D3 DD = TFalse
+type instance  DigitEq D4 DD = TFalse
+type instance  DigitEq D5 DD = TFalse
+type instance  DigitEq D6 DD = TFalse
+type instance  DigitEq D7 DD = TFalse
+type instance  DigitEq D8 DD = TFalse
+type instance  DigitEq D9 DD = TFalse
+type instance  DigitEq DA DD = TFalse
+type instance  DigitEq DB DD = TFalse
+type instance  DigitEq DC DD = TFalse
+type instance  DigitEq DD DD = TTrue
+type instance  DigitEq DE DD = TFalse
+type instance  DigitEq DF DD = TFalse
+type instance  DigitEq D0 DE = TFalse
+type instance  DigitEq D1 DE = TFalse
+type instance  DigitEq D2 DE = TFalse
+type instance  DigitEq D3 DE = TFalse
+type instance  DigitEq D4 DE = TFalse
+type instance  DigitEq D5 DE = TFalse
+type instance  DigitEq D6 DE = TFalse
+type instance  DigitEq D7 DE = TFalse
+type instance  DigitEq D8 DE = TFalse
+type instance  DigitEq D9 DE = TFalse
+type instance  DigitEq DA DE = TFalse
+type instance  DigitEq DB DE = TFalse
+type instance  DigitEq DC DE = TFalse
+type instance  DigitEq DD DE = TFalse
+type instance  DigitEq DE DE = TTrue
+type instance  DigitEq DF DE = TFalse
+type instance  DigitEq D0 DF = TFalse
+type instance  DigitEq D1 DF = TFalse
+type instance  DigitEq D2 DF = TFalse
+type instance  DigitEq D3 DF = TFalse
+type instance  DigitEq D4 DF = TFalse
+type instance  DigitEq D5 DF = TFalse
+type instance  DigitEq D6 DF = TFalse
+type instance  DigitEq D7 DF = TFalse
+type instance  DigitEq D8 DF = TFalse
+type instance  DigitEq D9 DF = TFalse
+type instance  DigitEq DA DF = TFalse
+type instance  DigitEq DB DF = TFalse
+type instance  DigitEq DC DF = TFalse
+type instance  DigitEq DD DF = TFalse
+type instance  DigitEq DE DF = TFalse
+type instance  DigitEq DF DF = TTrue
+
+type family    DigitsEq xs          ys
+type instance  DigitsEq TNil        TNil        = TTrue
+type instance  DigitsEq (x ::: xs)  TNil        = TFalse
+type instance  DigitsEq TNil        (x ::: xs)  = TFalse
+type instance  DigitsEq (x ::: xs)  (y ::: ys)  = TAnd (DigitEq x y) (DigitsEq xs ys)
+
+-- vim:set sw=4 ts=4 expandtab:
diff --git a/Generator/Array.hs b/Generator/Array.hs
new file mode 100644
--- /dev/null
+++ b/Generator/Array.hs
@@ -0,0 +1,47 @@
+--
+-- Define instance members (Candidates and Invoker), 
+--        constructors (Candidates and Invoker),
+--        properties, and
+--        supertypes (SupertypesOf)
+-- for all array types, in terms of the System.Array members they inherit.
+--
+-- Note that .NET arrays have no static members.
+--
+
+-- Instance methods for arrays are the same as the System.Array instance methods:
+type instance Candidates (Obj (Arr t)) member = Candidates (Obj Array_) member
+
+-- Delegate all array instance method invocations to System.Array:
+instance Invoker (Obj Array_) m args => Invoker (Obj (Arr t)) m args where
+  type Result (Obj (Arr t)) m args = Result (Obj Array_) m args
+  rawInvoke t m args = rawInvoke (convert t :: Obj Array_) m args
+
+
+-- There is one constructor for single-dimensional arrays which just calls the
+-- static Array.CreateInstance method passing the appropriate type and length:
+type instance Candidates (Arr t) Ctor = (Int32 ::: TNil) ::: TNil
+instance Typeable t => Invoker (Arr t) Ctor (Int32) where
+  type Result (Arr t) Ctor (Int32) = IO (Obj (Arr t))
+  rawInvoke t m (len) = liftM cast $ _Array # _createInstance (typeOf (undefined :: t), len)
+
+
+-- Delegate all array instance property gets/sets to System.Array:
+instance Prop (Obj Array_) pn => Prop (Obj (Arr t)) pn where
+  type PropGT (Obj (Arr t)) pn = PropGT (Obj Array_) pn
+  getProp t = getProp (convert t :: Obj Array_)
+  type PropST (Obj (Arr t)) pn = PropST (Obj Array_) pn
+  setProp t = setProp (convert t :: Obj Array_)
+
+-- All arrays derive directly from System.Array:
+type instance SupertypesOf (Obj (Arr t)) = (Obj Array_) ::: SupertypesOf (Obj Array_)
+
+
+-- Define the type code of single-dimension arrays in terms of the underlying
+-- element type:
+type instance TyCode (Obj (Arr t)) = D0 ::: DF ::: TyCode t
+-- (Note the use of 'DF' to separate the type code of the element from the type code 
+-- of arrays in general.)
+
+-- EXPERIMENTAL:
+type instance FromTyCode (D0 ::: DF ::: t) = Obj (Arr (FromTyCode t))
+
diff --git a/Generator/Generator.cs b/Generator/Generator.cs
new file mode 100644
--- /dev/null
+++ b/Generator/Generator.cs
@@ -0,0 +1,1326 @@
+//
+// Salsa Binding Generator
+//
+// Copyright: (c) 2007-2008 Andrew Appleyard
+// Licence:   BSD3 (see LICENSE)
+//
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using System.Reflection;
+using System.Linq;
+
+namespace Generator
+{
+    class Generator
+    {
+        static void Main(string[] args)
+        {
+            if (args.Length == 0)
+            {
+                Console.WriteLine("Usage: {0} [input-files]",
+                    Path.GetFileName(Environment.GetCommandLineArgs()[0]));
+            }
+            else
+                new Generator().Run(args);
+        }
+
+        private TextWriter w;
+
+        private Set<string> _labels = new Set<string>();
+        private Set<string> _invokers = new Set<string>();
+
+        /// <summary>
+        /// Instead of using long strings for identifiers inside the binding, we generate 
+        /// shorter, unique ids using this dictionary.
+        /// </summary>
+        private Dictionary<string, long> _uniqueIds = new Dictionary<string, long>();
+
+        private int _typeCodeMaxValue = 15;
+        private int _typeCodeValue = 7; // Leave first 7 codes available for primitive types
+
+        /// <summary>
+        /// Set of types that are required by the types generated so far.
+        /// </summary>
+        private Set<Type> _requiredTypes = new Set<Type>();
+
+        /// <summary>
+        /// Set of types that have been generated so far.
+        /// </summary>
+        private Set<Type> _generatedTypes = new Set<Type>();
+
+        /// <summary>
+        /// Set of types that were originally requested to be generated.
+        /// </summary>
+        private Set<Type> _requestedTypes = new Set<Type>();
+
+        private Dictionary<Type, List<string>> _requestedMembers = new Dictionary<Type, List<string>>();
+
+        private long GetUnique(params string[] keys)
+        {
+            string key = Util.Join("\0", keys); // Combine the keys
+            long id;
+            if (_uniqueIds.TryGetValue(key, out id))
+                return id;
+            else
+            {
+                id = _uniqueIds.Count + 1;
+                _uniqueIds.Add(key, id);
+                return id;
+            }
+        }
+
+        /// <summary>
+        /// Returns a unique type-level list of booleans, which can be used as a type code.
+        /// </summary>
+        private string GetNextTypeCode()
+        {
+            const int encodingBase = 15; 
+            // Note: This is not 16, thus leaving 'DF' available to use as a delimiter in type codes
+            //       for parameterised types (like arrays).
+
+            // Build a string for type code (as a Haskell type)
+            StringBuilder s = new StringBuilder();
+            int x = _typeCodeValue;
+            int b = _typeCodeMaxValue;
+            while (b > 1)
+            {
+                s.AppendFormat("{0} ::: ", 
+                    new string[] { 
+                        "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", 
+                        "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF" }[x % encodingBase]);
+                x /= encodingBase;
+                b /= encodingBase; 
+            }
+            s.Append("TNil");
+
+            // Obtain the next type code
+            _typeCodeValue += 1;
+            if (_typeCodeValue == _typeCodeMaxValue)
+            {
+                _typeCodeValue = 0;
+                _typeCodeMaxValue *= encodingBase;
+            }
+
+            return s.ToString();
+        }
+
+        private void RequestAll(Type t)
+        {
+            _requestedTypes.Add(t);
+
+            List<string> ms;// = new List<string>();
+            if (!_requestedMembers.TryGetValue(t, out ms))
+                ms = new List<string>();
+
+            foreach (MemberInfo mi in t.GetMembers(BindingFlags.Public |
+                BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly))
+                ms.Add(mi.Name);  
+
+            _requestedMembers[t] = ms;
+        }
+
+        private void Request(Type t, params string[] members)
+        {
+            _requestedTypes.Add(t);
+
+            List<string> ms;// = new List<string>();
+            if (!_requestedMembers.TryGetValue(t, out ms))
+                ms = new List<string>();
+            ms.AddRange(members);
+            _requestedMembers[t] = ms;
+        }
+
+        /// <summary>
+        /// Returns true iff the given member 'm' in type 't' has been requested,
+        /// either directly or indirectly (i.e. if 'm' is inherited from a 
+        /// requested member).
+        /// </summary>
+        private bool IsMemberRequested(Type targetType, string m)
+        {
+            List<string> ms;
+
+            foreach (Type t in EnumerateAncestors(targetType))
+            {
+                // Was the member requested in a supertype?
+                if (_requestedMembers.TryGetValue(t, out ms))
+                {
+                    if (ms.Contains(m))
+                        return true;
+                }
+            }
+            return false;
+        }
+
+        private void ReadImports(string path)
+        {
+            List<Assembly> references = new List<Assembly>();
+            references.Add(Assembly.GetAssembly(typeof(object)));
+
+            using (StreamReader r = File.OpenText(path))
+            {
+                string line;
+                while ((line = r.ReadLine()) != null)
+                {
+                    if (line.Trim() == string.Empty) continue;
+                    if (line.StartsWith("--") || line.StartsWith("#"))
+                        continue;
+
+                    string[] sides = line.Split(new char[] { ':', ' ', '\t' }, 2,
+                        StringSplitOptions.RemoveEmptyEntries);
+
+
+                    if (sides[0] == "reference")
+                    {
+                        if (sides.Length != 2)
+                            throw new Exception("Must specify assembly name after 'reference'");
+                        references.Add(Assembly.LoadFile(Path.GetFullPath(sides[1])));
+                    }
+                    else
+                    {
+                        string[] members;
+                        if (sides.Length > 1)
+                            members = sides[1].Split(new char[] { ',', ' ', '\t' },
+                                StringSplitOptions.RemoveEmptyEntries);
+                        else
+                            members = new string[0];
+
+                        bool foundType = false;
+                        foreach (Assembly a in references)
+                        {
+                            Type t = a.GetType(sides[0]);
+                            if (t != null)
+                            {
+                                if (members.Length > 0 && members[0] == "*")
+                                    RequestAll(t);
+                                else
+                                    Request(t, members);
+                                foundType = true;
+                                break;
+                            }
+                        }
+
+                        if (!foundType)
+                            throw new Exception(string.Format(
+                                "The type '{0}' does not exist (are you missing an assembly reference?)",
+                                sides[0]));
+                    }
+                }
+            }
+        }
+
+        private void Run(string[] args)
+        {
+            string outputPath = @".";
+
+            foreach (string arg in args)
+                ReadImports(arg);
+
+            // Require System.Array (the base class of all arrays), and its
+            // CreateInstance method, because the Salsa library uses it to 
+            // instantiate arrays.
+            Request(typeof(System.Array), "CreateInstance");
+
+            using (w = File.CreateText(Path.Combine(outputPath, "Bindings.hs")))
+            {
+                // Explicitly request all supertypes too (since their members are inherited 
+                // by the requested types)
+                foreach (Type requestedType in Enumerable.ToList(_requestedTypes))
+                {
+                    foreach (Type superRequestedType in EnumerateAncestors(requestedType))
+                    {
+                        _requestedTypes.Add(superRequestedType);
+                        
+                        if (_requestedMembers.ContainsKey(requestedType))
+                            Request(superRequestedType, _requestedMembers[requestedType].ToArray());
+                    }
+                }
+
+                foreach (Type requestedType in _requestedTypes)
+                {
+                    RequireType(requestedType);
+                    if (!_requestedMembers.ContainsKey(requestedType))
+                        _requestedMembers.Add(requestedType, new List<string>());
+                }
+
+                w.WriteLine("{-# LANGUAGE ForeignFunctionInterface, MultiParamTypeClasses, FlexibleInstances, TypeFamilies, TypeOperators, TypeSynonymInstances #-}");
+                w.WriteLine("{-# OPTIONS_GHC -fallow-undecidable-instances #-}");
+
+                w.WriteLine("module {0} (", "Bindings");
+                w.WriteLine("  module Labels");
+                w.WriteLine("  ) where");
+                w.WriteLine();
+                w.WriteLine("import Labels");
+                w.WriteLine("import Foreign.Salsa.Binding");
+
+                while (_requiredTypes.Count > 0)
+                {
+                    Type t = _requiredTypes.Pop();
+                    if (_generatedTypes.Contains(t)) continue; // Already generated
+
+                    if (IsUnsupportedType(t)) continue;
+                    if (IsPrim(t)) continue; // TODO: Support boxed primitive types later.
+
+                    Console.WriteLine("Binding " + t.ToString());
+                    WriteClass(t);
+
+                    _generatedTypes.Add(t);
+                }
+
+                Console.WriteLine("Generated bindings for {0} classes", _generatedTypes.Count);
+            }
+
+            using (w = File.CreateText(Path.Combine(outputPath, "Labels.hs")))
+            {
+                w.WriteLine("module Labels where");
+                w.WriteLine("import Foreign.Salsa (invoke)");
+                w.WriteLine();
+                WriteLabels();
+                WriteInvokers();
+            }
+        }
+
+        /// <summary>
+        /// Indicates that a particular type should be generated (if it hasn't
+        /// already been generated).
+        /// </summary>
+        private void RequireType(Type t)
+        {
+            if (!_generatedTypes.Contains(t))
+                _requiredTypes.Add(t);
+        }
+
+        private void WriteClass(Type targetType)
+        {
+            if (targetType.IsArray)
+            {
+                // Explicit bindings for array types are not generated by the code generator.
+                // We only need to generate bindings for the element type, the base type
+                // (System.Array) (which is always generated) and the parameterised 'Arr t'
+                // type (see end of this method).
+
+                // Require the element type of the array
+                RequireType(targetType.GetElementType());
+
+                return;
+            }
+
+            string classLabel = TypeToLabel(targetType);
+
+            w.WriteLine();
+            w.WriteLine("--");
+            w.WriteLine("-- Class: {0}", targetType.FullName);
+            w.WriteLine("--");
+            w.WriteLine();
+
+
+            //
+            // Write a Salsa.Typeable instance for this class
+            //
+            // Note: Type.GetType always returns the same instance for a given type, so it is 
+            //       safe to use 'unsafePerformIO' below.
+            //
+            w.WriteLine("instance Typeable {0} where", classLabel);
+            w.WriteLine("  typeOf _ = unsafePerformIO $ type_GetType \"{0}\"", targetType.AssemblyQualifiedName);
+            w.WriteLine();
+
+            // TODO: Cache result of 'typeOf' in an IORef?
+
+            {
+                //
+                // Instance and static methods
+                //
+                {
+                    // Build a list of relevant instance methods for the target class.
+                    // Filter out 'override' methods and 'get/set/add/remove' methods.
+                    // Also filter out methods with the same name and signature in a base 
+                    // class (i.e. hide by signature).
+                    List<MemberInfo> relevantMethods = new List<MemberInfo>();
+
+                    // Go down the inheritance tree from object to the target type
+                    foreach (Type implementedType in Enumerable.Reverse(EnumerateAncestors(targetType)))
+                    {
+                        foreach (MethodInfo mi in implementedType.GetMethods(
+                            BindingFlags.DeclaredOnly | BindingFlags.Public |
+                            BindingFlags.Instance | BindingFlags.Static))
+                        {
+                            if (mi.IsSpecialName) continue; // Skip get/set/add/remove methods
+
+                            // Skip overridden (virtual but not a new slot) methods
+                            if (mi.IsVirtual && (mi.Attributes & MethodAttributes.NewSlot) == 0) continue;
+
+                            // Ignore methods containing parameters of unsupported types, or an 
+                            // unsupported result type
+                            if (IsUnsupportedType(mi.ReturnType) ||
+                                Enumerable.Any(mi.GetParameters(),
+                                    delegate(ParameterInfo pi) { return IsUnsupportedType(pi.ParameterType); }))
+                                continue;
+
+                            // Remove any methods (from base classes) with this name and signature
+                            // (i.e. implement hide-by-signature semantics, like C#)
+                            relevantMethods.RemoveAll(delegate(MemberInfo mi2)
+                            {
+                                return HasSameSignature((MethodInfo)mi, (MethodInfo)mi2);
+                            });
+
+                            relevantMethods.Add(mi);
+                        }
+                    }
+
+                    // Enumerate over the method groups in the relevant instance methods,
+                    // generating bindings for each group
+                    foreach (IGrouping<string, MemberInfo> mg in Enumerable.GroupBy<MemberInfo, string>(
+                        relevantMethods, delegate(MemberInfo mi)
+                        {
+                            return (((MethodInfo)mi).IsStatic ? "static " : "") + mi.Name;
+                        }))
+                    {
+                        if (!IsMemberRequested(targetType, Enumerable.First(mg).Name)) continue;
+
+                        w.WriteLine("-- " + mg.Key);
+
+                        WriteMethodGroup(mg, targetType);
+                    }
+                }
+
+                //
+                // Constructors
+                //
+                if (typeof(Delegate).IsAssignableFrom(targetType))
+                {
+                    // Delegate constructors are special, since they accept a normal 
+                    // Haskell function as an argument
+                    WriteDelegateConstructor(targetType);
+                }
+                else
+                {
+                    // Build a list of relevant constructors for the target class (if any)
+                    List<ConstructorInfo> relevantConstructors = new List<ConstructorInfo>();
+                    foreach (ConstructorInfo ci in targetType.GetConstructors())
+                    {
+                        // Ignore methods containing parameters of unsupported types
+                        if (Enumerable.Any(ci.GetParameters(),
+                            delegate(ParameterInfo pi) { return IsUnsupportedType(pi.ParameterType); }))
+                            continue;
+
+                        relevantConstructors.Add(ci);
+                    }
+
+                    if (relevantConstructors.Count > 0)
+                    {
+                        // Generate bindings for the constructors (treated as a single method group)
+                        w.WriteLine("-- Constructors");
+                        WriteConstructorGroup(relevantConstructors, targetType);
+                        w.WriteLine();
+                    }
+                }
+
+                //
+                // Instance and static properties
+                //
+                {
+                    // Build a list accessors for accessable, non-indexed, properties in the target class
+                    List<AccessorInfo<PropertyInfo>> relevantPropertyAccessors =
+                        new List<AccessorInfo<PropertyInfo>>();
+
+                    // Go down the inheritance tree from object to the target type
+                    foreach (Type implementedType in Enumerable.Reverse(EnumerateAncestors(targetType)))
+                    {
+                        foreach (PropertyInfo pi in implementedType.GetProperties(
+                            BindingFlags.DeclaredOnly | BindingFlags.Public |
+                            BindingFlags.Instance | BindingFlags.Static))
+                        {
+                            // Ignore indexed properties (since they're currently out of scope, FIXME)
+                            if (pi.GetIndexParameters().Length > 0)
+                                continue;
+
+                            // Ignore properties of unsupported types
+                            if (IsUnsupportedType(pi.PropertyType)) continue;
+
+                            foreach (MethodInfo mi in pi.GetAccessors())
+                            {
+                                // Skip static properties declared outside of the target type
+                                AccessorInfo<PropertyInfo> ai = new AccessorInfo<PropertyInfo>(
+                                    mi == pi.GetGetMethod() ? AccessorType.Get : AccessorType.Set,
+                                    pi, mi);
+
+                                // Remove any shadowed properties (from base classes)
+                                relevantPropertyAccessors.RemoveAll(
+                                    delegate(AccessorInfo<PropertyInfo> ai2)
+                                    {
+                                        return HasSameSignature(ai.Accessor, ai2.Accessor);
+                                    });
+
+                                relevantPropertyAccessors.Add(ai);
+                            }
+                        }
+                    }
+
+                    // Enumerate over the properties and generate attribute bindings for each
+                    // pair of get/set accessors
+                    foreach (IGrouping<string, AccessorInfo<PropertyInfo>> mg in
+                        Enumerable.GroupBy<AccessorInfo<PropertyInfo>, string>(
+                            relevantPropertyAccessors,
+                            delegate(AccessorInfo<PropertyInfo> ai)
+                            {
+                                return (ai.Accessor.IsStatic ? "static " : "") + ai.Owner.Name;
+                            }))
+                    {
+                        if (!IsMemberRequested(targetType, Enumerable.First(mg).Owner.Name)) continue;
+
+                        WriteProperty(mg, targetType);
+                    }
+                }
+
+                //
+                // Static and instance events
+                //
+                {
+                    // Build a list accessors for events in the target class
+                    List<AccessorInfo<EventInfo>> relevantEventAccessors =
+                        new List<AccessorInfo<EventInfo>>();
+
+                    // Go down the inheritance tree from object to the target type
+                    foreach (Type implementedType in Enumerable.Reverse(EnumerateAncestors(targetType)))
+                    {
+                        foreach (EventInfo ei in implementedType.GetEvents(
+                            BindingFlags.DeclaredOnly | BindingFlags.Public |
+                            BindingFlags.Instance | BindingFlags.Static))
+                        {
+                            // Ignore events of unsupported types
+                            if (IsUnsupportedType(ei.EventHandlerType)) continue;
+
+                            foreach (MethodInfo mi in new MethodInfo[] {
+                            ei.GetAddMethod(), ei.GetRemoveMethod() })
+                            {
+                                // Skip static events declared outside of the target type
+                                AccessorInfo<EventInfo> ai = new AccessorInfo<EventInfo>(
+                                    mi == ei.GetAddMethod() ? AccessorType.Add : AccessorType.Remove,
+                                    ei, mi);
+
+                                // Remove any shadowed events (from base classes)
+                                relevantEventAccessors.RemoveAll(
+                                    delegate(AccessorInfo<EventInfo> ai2)
+                                    {
+                                        return HasSameSignature(ai.Accessor, ai2.Accessor);
+                                    });
+
+                                relevantEventAccessors.Add(ai);
+                            }
+                        }
+                    }
+
+                    // Enumerate over the events and generate attribute bindings for each
+                    // pair of add/remove accessors
+                    foreach (IGrouping<string, AccessorInfo<EventInfo>> mg in
+                        Enumerable.GroupBy<AccessorInfo<EventInfo>, string>(
+                            relevantEventAccessors,
+                            delegate(AccessorInfo<EventInfo> ai)
+                            {
+                                return (ai.Accessor.IsStatic ? "static " : "") + ai.Owner.Name;
+                            }))
+                    {
+                        if (!IsMemberRequested(targetType, Enumerable.First(mg).Owner.Name)) continue;
+
+                        WriteEvent(mg, targetType);
+                    }
+                }
+
+                //
+                // Instance and static fields
+                //
+                {
+                    // Build a list accessible fields in the target class
+                    List<FieldInfo> relevantFields = new List<FieldInfo>();
+
+                    // Go down the inheritance tree from object to the target type
+                    foreach (Type implementedType in Enumerable.Reverse(EnumerateAncestors(targetType)))
+                    {
+                        foreach (FieldInfo fi in implementedType.GetFields(
+                            BindingFlags.DeclaredOnly | BindingFlags.Public |
+                            BindingFlags.Instance | BindingFlags.Static))
+                        {
+                            // Ignore fields of unsupported types
+                            if (IsUnsupportedType(fi.FieldType)) continue;
+
+                            // Remove any shadowed fields (from base classes)
+                            relevantFields.RemoveAll(
+                                delegate(FieldInfo fi2)
+                                {
+                                    return fi.Name == fi2.Name;
+                                });
+
+                            relevantFields.Add(fi);
+                        }
+                    }
+
+                    // Enumerate over the fields and generate bindings for each
+                    foreach (FieldInfo fi in relevantFields)
+                    {
+                        if (!IsMemberRequested(targetType, fi.Name)) continue;
+
+                        WriteField(fi, targetType);
+                    }
+                }
+            }
+
+            //
+            // Ancestors
+            //
+
+            List<Type> supertypes = new List<Type>();
+
+            foreach (Type t in EnumerateAncestors(targetType))
+                supertypes.Add(t);
+
+            supertypes.AddRange(targetType.GetInterfaces());
+
+            // Remove any unsupported types from 'supertypes'
+            foreach (Type t in Enumerable.ToList(supertypes))
+            {
+                if (IsUnsupportedType(t))
+                    supertypes.Remove(t);
+            }
+
+            w.WriteLine("type instance SupertypesOf {0} = {1}", 
+                ToHaskellType(targetType),
+                Util.JoinSuffix(" ::: ", Enumerable.Select<Type, string>(supertypes,
+                    delegate(Type t) { return ToHaskellType(t); }), "TNil"));
+
+            foreach (Type supertype in supertypes)
+                RequireType(supertype);
+
+            //
+            // Type code
+            //
+            string typeCode = GetNextTypeCode();
+            w.WriteLine("type instance TyCode {0} = {1}", ToHaskellType(targetType), typeCode);
+            w.WriteLine("type instance FromTyCode ({1}) = {0}", ToHaskellType(targetType), typeCode); // EXPERIMENTAL
+            w.WriteLine();
+
+            if (targetType == typeof(System.Array))
+            {
+                //
+                // Delegate the members of any array type (i.e. any 'Arr t') to System.Array
+                //
+                w.WriteLine();
+                w.WriteLine("--");
+                w.WriteLine("-- 'Arr t' to 'System.Array' delegation code");
+                w.WriteLine("--");
+                w.WriteLine();
+                Console.WriteLine(string.Join(", ", Assembly.GetExecutingAssembly().GetManifestResourceNames()));
+                using (StreamReader r = new StreamReader(
+                    Assembly.GetExecutingAssembly().GetManifestResourceStream(typeof(Generator), "Array.hs")))
+                {
+                    string line;
+                    while ((line = r.ReadLine()) != null)
+                        w.WriteLine(line);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Generates bindings for a delegate constructor for the given delegate type.
+        /// </summary>
+        private void WriteDelegateConstructor(Type delegateType)
+        {
+            string classLabel = TypeToLabel(delegateType);
+
+            w.WriteLine();
+            w.WriteLine("--");
+            w.WriteLine("-- Delegate: {0}", delegateType.Name);
+            w.WriteLine("--");
+            w.WriteLine();
+
+            if (delegateType != typeof(Delegate) &&
+                delegateType != typeof(MulticastDelegate))
+            {
+                ConstructorInfo constructorCi = delegateType.GetConstructors()[0];
+                MethodInfo invokerMi = delegateType.GetMethod("Invoke");
+
+                string target = TypeToLabel(delegateType);
+
+                string stubFunction = ToStubName(constructorCi);
+                string wrapperFunction = "wrap_" + stubFunction;
+                string wrapperType = "Type_" + wrapperFunction;
+
+                ParameterInfo[] parameters = GetParameters(invokerMi);
+
+                // Generate the base type signature for Haskell implementation of the delegate
+                w.WriteLine("type {0} = {1}", wrapperType,
+                    Util.JoinSuffix(" -> ", Enumerable.Select<ParameterInfo, string>(parameters,
+                        delegate(ParameterInfo pi) { return ToBaseType(pi.ParameterType); }),
+                        ToBaseReturnType(GetMemberReturnType(invokerMi))));
+
+                w.WriteLine("foreign import stdcall \"wrapper\" {0} :: {1} -> (IO (FunPtr {1}))",
+                    wrapperFunction, wrapperType);
+                w.WriteLine();
+
+                // Generate the delegate-object-generating stub function
+                w.WriteLine("{{-# NOINLINE {0} #-}}", stubFunction);
+                w.WriteLine("{0} :: {1} -> IO ObjectId", stubFunction, wrapperType);
+                w.WriteLine("{0} = unsafePerformIO $ getDelegateConstructorStub", stubFunction);
+                w.WriteLine("    \"{0}\"", delegateType.AssemblyQualifiedName);
+                w.WriteLine("    {0}", wrapperFunction);
+                w.WriteLine();
+
+                // Generate the 'delegate' instance for calling the delegate constructor
+                w.WriteLine("instance Delegate {0} where", target);
+                w.WriteLine("    type DelegateT {0} = {1}", target,
+                    Util.JoinSuffix(" -> ", Enumerable.Select<ParameterInfo, string>(parameters,
+                        delegate(ParameterInfo pi) { return ToHaskellType(pi.ParameterType); }),
+                        ToReturnType(GetMemberReturnType(invokerMi))));
+                w.WriteLine("    delegate _ handler = {0} (marshalFn{1} handler) >>= unmarshal",
+                    stubFunction, parameters.Length);
+                w.WriteLine();
+            }
+
+            w.WriteLine();
+        }
+        
+        /// <summary>
+        /// Generates bindings for a method group containing: all instance methods,
+        /// all static methods, or all instance constructors.
+        /// </summary>
+        private void WriteMethodGroup(IEnumerable<MemberInfo> members, Type forType)
+        {
+            MemberInfo firstMi = Enumerable.First(members);
+
+            Console.WriteLine("  {0}", firstMi.Name);
+
+            ParameterInfo[] parameters = GetParameters(firstMi);
+            Type returnType = GetMemberReturnType(firstMi);
+            bool isStatic = IsMemberStatic(firstMi);
+
+            string label = GetMemberLabel(firstMi);
+            string target = isStatic ? TypeToLabel(forType) : ToHaskellType(forType);
+
+            // Output the parameter lists for the members of the method group
+            w.WriteLine("type instance Candidates {0} {1} = {2}",
+                target, label,
+                Util.JoinSuffix(" ::: ", Enumerable.Select<MemberInfo, string>(members,
+                    delegate(MemberInfo mi) { return ToListType(GetParameters(mi)); }), "TNil"));
+
+            // Output instances for invoking each method group member
+            foreach (MemberInfo mi in members)
+                WriteMethod(mi, forType);
+            w.WriteLine();
+
+            // Require the return type of this method
+            RequireType(returnType);
+        }
+
+        /// <summary>
+        /// Generates bindings for a group of instance constructors.
+        /// </summary>
+        private void WriteConstructorGroup(IEnumerable<ConstructorInfo> members, Type forType)
+        {
+            ConstructorInfo firstCi = Enumerable.First(members);
+            string target = TypeToLabel(forType);
+            string label = "Ctor";
+
+            // Output the parameter lists for the constructors
+            w.WriteLine("type instance Candidates {0} {1} = {2}",
+                target, label,
+                Util.JoinSuffix(" ::: ", Enumerable.Select<ConstructorInfo, string>(members,
+                    delegate(ConstructorInfo ci) { return ToListType(ci.GetParameters()); }), "TNil"));
+
+            // Output instances for invoking each constructor
+            foreach (ConstructorInfo ci in members)
+                WriteMethod(ci, forType);
+        }
+
+        /// <summary>
+        /// Generate bindings for a static method, instance method, or instance constructor,
+        /// for use in a particular class (which, in the case of an instance method, may be a
+        /// descendant of the class in which the method was declared).
+        /// </summary>
+        private void WriteMethod(MemberInfo mi, Type forType)
+        {
+            // If the method was declared on the target type (forType), then produce
+            // the FFI stub function (which is called by Invoker instances down the
+            // hierarchy)
+            if (mi.DeclaringType == forType)
+                WriteMethodStub(mi);
+
+            // Invoker instance:
+            w.WriteLine("instance Invoker {0} {1} {2} where",
+                IsMemberStatic(mi) ? TypeToLabel(forType) : ToHaskellType(forType),
+                GetMemberLabel(mi), ToTupleType(GetParameters(mi)));
+            w.WriteLine("  type Result {0} {1} {2} = {3}",
+                IsMemberStatic(mi) ? TypeToLabel(forType) : ToHaskellType(forType),
+                GetMemberLabel(mi), ToTupleType(GetParameters(mi)),
+                ToReturnType(GetMemberReturnType(mi)));
+            w.WriteLine("  rawInvoke = {0}", ToMethodMarshaler(mi));
+
+            // Require any parameter types for this method/constructor
+            foreach (ParameterInfo pi in GetParameters(mi))
+                RequireType(pi.ParameterType);
+        }
+        
+        /// <summary>
+        /// Returns true iff the given member should be treated as a static member.
+        /// Static methods, static properties, and instance constructors are all
+        /// treated as static members.
+        /// </summary>
+        private bool IsMemberStatic(MemberInfo mi)
+        {
+            if (mi is ConstructorInfo)
+                return true;
+            if (mi is MethodInfo)
+                return ((MethodInfo)mi).IsStatic;
+            if (mi is FieldInfo)
+                return ((FieldInfo)mi).IsStatic;
+            throw new ArgumentException("Expected a ConstructorInfo, MethodInfo or FieldInfo.");
+        }
+
+        /// <summary>
+        /// Returns the Haskell code for a function that calls the given method, 
+        /// constructor, or property accessor, marshaling the arguments and result 
+        /// value as necessary.
+        /// </summary>
+        private string ToMethodMarshaler(MemberInfo mi)
+        {
+            return string.Format("marshalMethod{0}{1} {2}",
+                GetParameters(mi).Length, IsMemberStatic(mi) ? "s" : "i",
+                ToStubName(mi));
+        }
+
+        /// <summary>
+        /// Generates an FFI stub function for calling a particular .NET method
+        /// or property accessor.
+        /// </summary>
+        private void WriteMethodStub(MemberInfo mi)
+        {
+            // TODO: Perhaps use unboxed string literals?
+
+            string stubFunction = ToStubName(mi);
+            string stubType = "Type_" + stubFunction;
+            string makeFunction = "make_" + stubFunction;
+
+            w.WriteLine();
+            w.WriteLine("-- Foreign Interface Stub for {0}.{1}:",
+                mi.DeclaringType.Name, mi.Name);
+            w.WriteLine("type {0} = {1}{2}", stubType,
+                IsMemberStatic(mi) ? "" : (ToBaseType(mi.DeclaringType) + " -> "),
+                Util.JoinSuffix(" -> ", Enumerable.Select<ParameterInfo, string>(GetParameters(mi),
+                    delegate(ParameterInfo pi) { return ToBaseType(pi.ParameterType); }),
+                    ToBaseReturnType(GetMemberReturnType(mi))));
+            w.WriteLine("foreign import stdcall \"dynamic\" {0} :: FunPtr {1} -> {1}",
+                makeFunction, stubType);
+            w.WriteLine();
+            w.WriteLine("{{-# NOINLINE {0} #-}}", stubFunction);
+            w.WriteLine("{0} :: {1}", stubFunction, stubType);
+            w.WriteLine("{0} = {1} $ unsafePerformIO $ getMethodStub", stubFunction, makeFunction);
+            w.WriteLine("    \"{0}\" \"{1}\"", mi.DeclaringType.AssemblyQualifiedName, mi.Name);
+            w.WriteLine("    \"{0}\"",
+                Util.Join(";", Enumerable.Select<ParameterInfo, string>(GetParameters(mi),
+                    delegate(ParameterInfo pi) { return ToQualifiedType(pi.ParameterType); })));
+            w.WriteLine();
+        }
+
+        /// <summary>
+        /// Generates FFI stub functions for retrieving or setting a particular .NET field.
+        /// </summary>
+        private void WriteFieldStub(FieldInfo fi, AccessorType accessorType)
+        {
+            bool isGet = (accessorType == AccessorType.Get);
+            string stubFunction = ToStubName(fi) + "_" + (isGet ? "get" : "set");
+            string stubType = "Type_" + stubFunction;
+            string makeFunction = "make_" + stubFunction;
+
+            w.WriteLine();
+            w.WriteLine("-- Field accessor stub for {0}.{1}:", fi.DeclaringType.Name, fi.Name);
+            w.WriteLine("type {0} = {1}{2}{3}", 
+                stubType,
+                fi.IsStatic ? "" : (ToBaseType(fi.DeclaringType) + " -> "),
+                isGet ? "" : (ToBaseType(fi.FieldType) + " -> "),
+                isGet ? ToBaseReturnType(fi.FieldType) : "IO ()");
+
+            w.WriteLine("foreign import stdcall \"dynamic\" {0} :: FunPtr {1} -> {1}",
+                makeFunction, stubType);
+
+            w.WriteLine();
+            w.WriteLine("{{-# NOINLINE {0} #-}}", stubFunction);
+            w.WriteLine("{0} :: {1}", stubFunction, stubType);
+            w.WriteLine("{0} = {1} $ unsafePerformIO $ {2}", stubFunction, makeFunction,
+                isGet ? "getFieldGetStub" : "getFieldSetStub");
+            w.WriteLine("    \"{0}\" \"{1}\"", fi.DeclaringType.AssemblyQualifiedName, fi.Name);
+            w.WriteLine();
+        }
+
+        private void WriteProperty(IEnumerable<AccessorInfo<PropertyInfo>> accessors, Type forType)
+        {
+            AccessorInfo<PropertyInfo> firstAccessor = Enumerable.First(accessors);
+            bool isStatic = IsMemberStatic(firstAccessor.Accessor);
+
+            string target = isStatic ? TypeToLabel(forType) : ToHaskellType(forType);
+            string label = ToLabelType(firstAccessor.Owner.Name);
+
+            w.WriteLine("instance Prop {0} {1} where", target, label);
+
+            AccessorInfo<PropertyInfo> getAccessor = Enumerable.FirstOrDefault(accessors,
+                delegate(AccessorInfo<PropertyInfo> ai) { return ai.Type == AccessorType.Get; });
+            AccessorInfo<PropertyInfo> setAccessor = Enumerable.FirstOrDefault(accessors,
+                delegate(AccessorInfo<PropertyInfo> ai) { return ai.Type == AccessorType.Set; });
+
+            if (getAccessor != null)
+            {
+                w.WriteLine("    type PropGT {0} {1} = {2}", target, label,
+                    ToHaskellType(getAccessor.Owner.PropertyType));
+                w.WriteLine("    getProp t pn = {0} t pn ()", ToMethodMarshaler(getAccessor.Accessor));
+            }
+            else
+            {
+                w.WriteLine("    type PropGT {0} {1} = ()", target, label);
+                w.WriteLine("    getProp _ _ = return ()"); // Return nothing
+            }
+
+            if (setAccessor != null)
+            {
+                w.WriteLine("    type PropST {0} {1} = {2}", target, label,
+                    ToHaskellType(setAccessor.Owner.PropertyType));
+                w.WriteLine("    setProp = {0}", ToMethodMarshaler(setAccessor.Accessor));
+            }
+            else
+            {
+                w.WriteLine("    type PropST {0} {1} = ()", target, label);
+                w.WriteLine("    setProp _ _ _ = return ()"); // Do nothing
+            }
+            
+            foreach (AccessorInfo<PropertyInfo> accessor in accessors)
+            {
+                // Generate the get/set stub caller (in declared type only)
+                if (accessor.Accessor.DeclaringType == forType)
+                    WriteMethodStub(accessor.Accessor);
+            }
+
+            w.WriteLine();
+        }
+
+        private void WriteEvent(IEnumerable<AccessorInfo<EventInfo>> accessors, Type forType)
+        {
+            AccessorInfo<EventInfo> firstAccessor = Enumerable.First(accessors);
+            bool isStatic = IsMemberStatic(firstAccessor.Accessor);
+
+            string target = isStatic ? TypeToLabel(forType) : ToHaskellType(forType);
+            string label = ToLabelType(firstAccessor.Owner.Name);
+
+            w.WriteLine("instance Event {0} {1} where", target, label);
+            w.WriteLine("    type EventT {0} {1} = {2}", target, label,
+                ToHaskellType(firstAccessor.Owner.EventHandlerType));
+
+            foreach (AccessorInfo<EventInfo> accessor in accessors)
+            {
+                if (accessor.Type == AccessorType.Add)
+                    w.WriteLine("    addEvent    = {0}", ToMethodMarshaler(accessor.Accessor));
+                else // AccessorType.Remove
+                    w.WriteLine("    removeEvent = {0}", ToMethodMarshaler(accessor.Accessor));
+            }
+
+            foreach (AccessorInfo<EventInfo> accessor in accessors)
+            {
+                // Generate the add/remove stub caller (in declared type only)
+                if (accessor.Accessor.DeclaringType == forType)
+                    WriteMethodStub(accessor.Accessor);
+            }
+
+            w.WriteLine();
+
+            // Require the event type of this event
+            RequireType(firstAccessor.Owner.EventHandlerType);
+        }
+
+        private void WriteField(FieldInfo field, Type forType)
+        {
+            bool isStatic = field.IsStatic;
+            bool isReadOnly = field.IsLiteral || field.IsInitOnly;
+
+            // TODO: Add support for literal fields.  The constant value from
+            //       the metadata should be included in the generated code.
+
+            string target = isStatic ? TypeToLabel(forType) : ToHaskellType(forType);
+            string label = ToLabelType(field.Name);
+
+            w.WriteLine("instance Prop {0} {1} where", target, label);
+
+            w.WriteLine("    type PropGT {0} {1} = {2}", target, label, ToHaskellType(field.FieldType));
+            w.WriteLine("    getProp t pn = marshalMethod0{0} {1}_get t pn ()",
+                isStatic ? "s" : "i", ToStubName(field));
+
+            if (!isReadOnly)
+            {
+                w.WriteLine("    type PropST {0} {1} = {2}", target, label, ToHaskellType(field.FieldType));
+                w.WriteLine("    setProp = marshalMethod1{0} {1}_set", 
+                    isStatic ? "s" : "i", ToStubName(field));
+            }
+            else
+            {
+                w.WriteLine("    type PropST {0} {1} = ()", target, label);
+                w.WriteLine("    setProp _ _ _ = return ()"); // Do nothing
+            }
+
+            // Generate the get/set stub caller (in declared type only)
+            if (field.DeclaringType == forType)
+            {
+                if (!isReadOnly)
+                    WriteFieldStub(field, AccessorType.Set);
+                WriteFieldStub(field, AccessorType.Get);
+            }
+
+            // For readonly fields, generate an IO-less method getting the value
+            if (isReadOnly)
+            {
+                // Ensure that an invoker is generated for invoking the label with '#'
+                ToInvoker(field.Name);
+
+                w.WriteLine("type instance Candidates {0} {1} = TNil ::: TNil", target, label);
+
+                w.WriteLine("instance Invoker {0} {1} () where", target, label);
+                w.WriteLine("  type Result {0} {1} () = {2}", target, label, ToHaskellType(field.FieldType));
+                w.WriteLine("  rawInvoke t m () = unsafePerformIO $ get t m ");
+            }
+
+            w.WriteLine();
+        }
+
+        private string ToHaskellType(Type t)
+        {
+            if (t == typeof(void)) return "()";
+            if (t == typeof(int)) return "Int32";
+            if (t == typeof(string)) return "String";
+            if (t == typeof(bool)) return "Bool";
+            if (t == typeof(Double)) return "Double";
+            if (t == typeof(bool?)) return "(Maybe Bool)";
+            if (t.IsArray) 
+                return string.Format("(Obj (Arr {0}))", ToHaskellType(t.GetElementType()));
+            return "(Obj " + TypeToLabel(t) + ")";
+        }
+
+        private string ToReturnType(Type t)
+        {
+            return "IO " + ToHaskellType(t);
+        }
+
+        /// <summary>
+        /// Gives the low-level Haskell type for the given .NET type 't'.  This is the
+        /// base type used in FFI declarations.
+        /// </summary>
+        private string ToBaseType(Type t)
+        {
+            if (t == typeof(void)) return "()";
+            if (t == typeof(Int32)) return "Int32";
+            if (t == typeof(String)) return "CWString";
+            if (t == typeof(Boolean)) return "Bool";
+            if (t == typeof(Double)) return "Double";
+            return "ObjectId";
+        }
+
+        private string ToBaseReturnType(Type t)
+        {
+            return "IO " + ToBaseType(t);
+        }
+
+        private bool IsPrim(Type t)
+        {
+            return
+                t == typeof(void) ||
+                t == typeof(Int32) ||
+                t == typeof(String) ||
+                t == typeof(Boolean) ||
+                t == typeof(Double);
+        }
+
+        private bool IsUnsupportedType(Type t)
+        {
+            return
+                t.Name.StartsWith("_") ||
+                t.IsByRef ||        // FIXME: Support this?
+                t.IsPointer ||
+                // Salsa doesn't support generic types yet, but there's a special case for Nullable<bool>
+                (t.IsGenericType && t != typeof(Nullable<bool>)) ||
+                t.IsGenericParameter ||
+                // Salsa only supports arrays of non-generic types at present
+                (t.IsArray && IsUnsupportedType(t.GetElementType()));
+        }
+
+        /// <summary>
+        /// Returns a tuple of high-level Haskell types corresponding to the given
+        /// list of method parameters.
+        /// </summary>
+        private string ToTupleType(ParameterInfo[] ts)
+        {
+            return "(" + Util.Join(", ", Enumerable.Select<ParameterInfo, string>(ts,
+                delegate(ParameterInfo pi) { return ToHaskellType(pi.ParameterType); } )) + ")";
+        }
+
+        /// <summary>
+        /// Returns a type-level list of high-level Haskell types corresponding to 
+        /// the given list of method parameters.
+        /// </summary>
+        private string ToListType(ParameterInfo[] ts)
+        {
+            return "(" + Util.JoinSuffix(" ::: ", Enumerable.Select<ParameterInfo, string>(ts,
+                delegate(ParameterInfo pi) { return ToHaskellType(pi.ParameterType); } ), "TNil") + ")";
+        }
+
+        /// <summary>
+        /// Returns the name of the raw FFI stub method associated with the given .NET method
+        /// or constructor.  There is a unique stub name for every declared method overload,
+        /// and constructor.
+        /// </summary>
+        private string ToStubName(MemberInfo mi)
+        {
+            string parameterDetails = "";
+            if (mi is ConstructorInfo || mi is MethodInfo)
+                parameterDetails = Util.Join(" ", Enumerable.Select<ParameterInfo, string>(GetParameters(mi),
+                        delegate(ParameterInfo pi) { return pi.ParameterType.AssemblyQualifiedName; }));
+
+            return string.Format("stub_{0}",
+                GetUnique("stub",
+                    mi.DeclaringType.AssemblyQualifiedName,
+                    mi.Name,
+                    parameterDetails));
+        }
+
+        /// <summary>
+        /// Returns the name of the FFI wrapper function that is used to wrap Haskell 
+        /// functions that implement the given .NET delegate type.
+        /// </summary>
+        private string ToWrapperName(Type dt)
+        {
+            return string.Format("wrap_{0}",
+                GetUnique("wrap", dt.AssemblyQualifiedName));
+        }
+
+        /// <summary>
+        /// Returns a string that uniquely identifies the given type.  It is 
+        /// used to retrieve stub functions for the particular type at runtime.
+        /// </summary>
+        private string ToQualifiedType(Type t)
+        {
+            // Unless the type is in mscorlib, use the (long) assembly qualified name
+            if (t.Assembly == typeof(object).Assembly)
+                return t.FullName;
+            else
+                return t.AssemblyQualifiedName;
+        }
+
+        private ParameterInfo[] GetParameters(MemberInfo mi)
+        {
+            if (mi is MethodInfo)
+                return ((MethodInfo)mi).GetParameters();
+            if (mi is ConstructorInfo)
+                return ((ConstructorInfo)mi).GetParameters();
+            throw new ArgumentException("Must be a MethodInfo or ConstructorInfo.", "mi");
+        }
+
+        private Type GetMemberReturnType(MemberInfo mi)
+        {
+            if (mi is MethodInfo)
+                return ((MethodInfo)mi).ReturnType;
+            if (mi is ConstructorInfo)
+                return ((ConstructorInfo)mi).DeclaringType;
+            throw new ArgumentException("Must be a MethodInfo or ConstructorInfo.", "mi");
+        }
+
+        private string GetMemberLabel(MemberInfo mi)
+        {
+            if (mi is MethodInfo)
+                return MethodToLabel((MethodInfo)mi);
+            if (mi is ConstructorInfo)
+                return "Ctor";
+            throw new ArgumentException("Must be a MethodInfo or ConstructorInfo.", "mi");
+        }
+
+        /// <summary>
+        /// Returns true iff the given methods have the same name, number and type of 
+        /// parameters.
+        /// </summary>
+        private bool HasSameSignature(MethodInfo mi1, MethodInfo mi2)
+        {
+            if (mi1.Name != mi2.Name) return false;
+            ParameterInfo[] pi1 = mi1.GetParameters();
+            ParameterInfo[] pi2 = mi2.GetParameters();
+            if (pi1.Length != pi2.Length) return false;
+            for (int i = 0; i < pi1.Length; i++)
+            {
+                if (pi1[i].ParameterType != pi2[i].ParameterType)
+                    return false;
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Returns an irrefutable Haskell pattern for matching a value of the given type.
+        /// 'index' is included in the identified used (if any).
+        /// </summary>
+        private string ToPattern(Type t, int index)
+        {
+            if (t == typeof(void)) return "()";
+            if (t == typeof(int) || t == typeof(bool) || t == typeof(string))
+                return string.Format("a{0}", index);
+            return string.Format("(Obj a{0})", index);
+        }
+
+        /// <summary>
+        /// Enumerate ancestors of 't', starting with 't' and finishing with object.
+        /// </summary>
+        private IEnumerable<Type> EnumerateAncestors(Type t)
+        {
+            while (t != null)
+            {
+                yield return t;
+                t = t.BaseType;
+            }
+        }
+
+        private string MethodToLabel(MethodInfo mi)
+        {
+            ToInvoker(mi.Name);
+            return ToLabelType(mi.Name);
+        }
+
+        private string TypeToLabel(Type t)
+        {
+            if (IsUnsupportedType(t)) return ToLabelType("NotSupported"); 
+
+            if (t.IsNested && t.DeclaringType != null)
+            {
+                // FIXME: This only handles one level of nested classes 
+                //        (and it doesn't handle nested generic types)
+                return ToLabelType(t.DeclaringType.Name + "_" + t.Name);
+            }
+            else if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
+            {
+                return string.Format("(Maybe {0})", TypeToLabel(t.GetGenericArguments()[0]));
+            }
+            else
+                return ToLabelType(t.Name);
+        }
+
+        private string ToLabelHelper(string s)
+        {
+            if (string.IsNullOrEmpty(s))
+                throw new ArgumentException("Expected non-empty string.");
+            s = char.ToUpper(s[0]) + s.Substring(1);
+            if (!_labels.Contains(s) && 
+                s != "Object" && s != "Type" && s != "Array") // These labels are defined in the Salsa library
+                _labels.Add(s);
+            return s;
+        }
+
+        private string ToLabelValue(string s)
+        {
+            return "_" + ToLabelHelper(s);
+        }
+
+        private string ToLabelType(string s)
+        {
+            return ToLabelHelper(s) + "_";
+        }
+
+        private void WriteLabels()
+        {
+            w.WriteLine("-- Labels for .NET types, methods, properties, fields and events");
+            foreach (string label in _labels)
+                w.WriteLine("data {0,-25}", ToLabelType(label));
+            w.WriteLine();
+            foreach (string label in _labels)
+                w.WriteLine("{0,-30} = undefined :: {1}", ToLabelValue(label), ToLabelType(label));
+            w.WriteLine();
+        }
+
+        private string ToInvoker(string s)
+        {
+            s = Util.ToLowerFirst(s);
+            if (!_invokers.Contains(s))
+                _invokers.Add(s);
+            return "_" + s;
+        }
+
+        private void WriteInvokers()
+        {
+            w.WriteLine("-- Functions for invoking methods with '#'");
+            foreach (string invoker in _invokers)
+            {
+                // Output an invoker (and a unit invoker, for convenience and consistency)
+                w.WriteLine("{0} args target = invoke target {1} args", ToInvoker(invoker), ToLabelValue(invoker));
+                w.WriteLine("{0}_ target = invoke target {1} ()", ToInvoker(invoker), ToLabelValue(invoker));
+            }
+            w.WriteLine();
+        }
+    }
+
+    public static class Util
+    {
+        public static string Join(string separator, IEnumerable<string> xs)
+        {
+            StringBuilder sb = new StringBuilder();
+            foreach (string x in xs)
+            {
+                sb.Append(x);
+                sb.Append(separator);
+            }
+            if (sb.Length > 0) sb.Length -= separator.Length;
+            return sb.ToString();
+        }
+
+        public static string JoinSuffix(string separator, IEnumerable<string> xs, string end)
+        {
+            StringBuilder sb = new StringBuilder();
+            foreach (string x in xs)
+            {
+                sb.Append(x);
+                sb.Append(separator);
+            }
+            sb.Append(end);
+            return sb.ToString();
+        }
+
+        public static string ToLowerFirst(string s)
+        {
+            if (s == "") return "";
+            return s.Substring(0, 1).ToLower() + s.Substring(1);
+        }
+
+        public static string ToUpperFirst(string s)
+        {
+            if (s == "") return "";
+            return s.Substring(0, 1).ToUpper() + s.Substring(1);
+        }
+    }
+
+    public class AccessorInfo<T> where T : MemberInfo
+    {
+        private AccessorType _type;
+        private T _owner;
+        private MethodInfo _accessor;
+
+        public AccessorInfo(AccessorType type, T owner, MethodInfo accessor)
+        {
+            _type = type;
+            _owner = owner;
+            _accessor = accessor;
+        }
+
+        public AccessorType Type
+        {
+            get { return _type; }
+        }
+
+        public MethodInfo Accessor
+        {
+            get { return _accessor; }
+        }
+
+        public T Owner
+        {
+            get { return _owner; }
+        }
+    }
+
+    public enum AccessorType { Get, Set, Add, Remove };
+}
diff --git a/Generator/Generator.csproj b/Generator/Generator.csproj
new file mode 100644
--- /dev/null
+++ b/Generator/Generator.csproj
@@ -0,0 +1,92 @@
+﻿<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{53648C35-67B5-4903-999C-54B19F4DEE75}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Generator</RootNamespace>
+    <AssemblyName>Generator</AssemblyName>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>2.0</OldToolsVersion>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Generator.cs" />
+    <Compile Include="Set.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Array.hs" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Properties\" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
diff --git a/Generator/README b/Generator/README
new file mode 100644
--- /dev/null
+++ b/Generator/README
@@ -0,0 +1,33 @@
+
+                           The Salsa Binding Generator
+
+  Generates Haskell modules (called 'Bindings' and 'Labels') that together
+  contain the binding code required to interface with specific .NET classes and
+  their members.  An import file provides a list of the classes and their
+  assemblies.
+
+Usage:
+
+  Generator.exe Project.imports
+
+  where 'Project.imports' is a file that lists (on separate lines):
+
+    * The classes to import (optionally followed by a comma-separated list of
+      the members from the class to import).  For example:
+
+      System.Environment                  (binds all members of the Environment
+                                           class)
+
+      System.Console: Write, WriteLine    (binds only the Write and WriteLine
+                                           methods of the Console class)
+
+    * The assemblies that hold the imported classes.  For example:
+
+      reference C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll
+
+      (to make a reference to the .NET 2.0 System assembly)
+
+Building:
+
+  Run 'msbuild' in the 'Generator' directory.
+
diff --git a/Generator/Set.cs b/Generator/Set.cs
new file mode 100644
--- /dev/null
+++ b/Generator/Set.cs
@@ -0,0 +1,61 @@
+//
+// Salsa Binding Generator
+//
+// Copyright: (c) 2007-2008 Andrew Appleyard
+// Licence:   BSD3 (see LICENSE)
+//
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Generator
+{
+    public class Set<T> : IEnumerable<T>
+    {
+        private Dictionary<T, object> _store = new Dictionary<T, object>();
+
+        public void Add(T v)
+        {
+            if (!_store.ContainsKey(v))
+                _store.Add(v, null);
+        }
+
+        public int Count
+        {
+            get { return _store.Count; }
+        }
+
+        public bool Contains(T v)
+        {
+            return _store.ContainsKey(v);
+        }
+
+        /// <summary>
+        /// Removes an item from the set and returns it.
+        /// </summary>
+        public T Pop()
+        {
+            foreach (T v in _store.Keys)
+            {
+                _store.Remove(v);
+                return v;
+            }
+            throw new InvalidOperationException("Set is empty.");
+        }
+
+        #region IEnumerable<T> implementation
+
+        public IEnumerator<T> GetEnumerator()
+        {
+            return _store.Keys.GetEnumerator();
+        }
+
+        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+        {
+            return _store.Keys.GetEnumerator();
+        }
+
+        #endregion
+    }
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2007-2008, Andrew Appleyard.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+ * The name of the copyright holder may not be used to endorse or promote
+   products derived from this software without specific prior written
+   permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,77 @@
+
+                      Salsa: a .NET bridge for Haskell
+                     
+  Salsa is an experimental Haskell library and code generator that allows
+  Haskell programs to host the .NET runtime and interact with .NET libraries.
+  It uses type families extensively to provide a type-safe mapping of the .NET
+  object model in the Haskell type system.
+
+What's in the package:
+
+  * 'Foreign' contains the Haskell library 'Foreign.Salsa'.  
+
+    This library provides the Haskell-side interface to Salsa, including:
+    functions to load the .NET runtime into the process, functions for
+    interacting with .NET classes and objects, and the required type-level
+    machinery.  It works together with the Haskell modules created by the
+    generator (see below) to provide access to .NET classes and their members.
+
+  * 'Driver' contains the Salsa .NET driver assembly (Salsa.dll).
+
+    The driver assembly contains .NET code that is loaded automatically by the
+    Salsa library when the .NET runtime is loaded into the process.  It
+    provides run-time code generation facilities for calling in and out of the
+    .NET runtime from Haskell.  The assembly binary (Salsa.dll) is embedded in
+    'Foreign\Salsa\Driver.hs' using the 'Embed.hs' utility program.
+
+  * 'Generator' contains the Salsa binding generator.
+
+    The generator is a C# program that creates Haskell modules from .NET
+    metadata to provide type-safe access to the requested .NET classes and
+    methods in .NET assembilies.
+    
+    Note: the generator requires .NET 3.5 because it uses the 'System.Linq'
+          namespace.
+
+  * 'Samples' contains a few Haskell programs that use Salsa.
+
+    - Hello:   a basic console 'Hello World' program.
+
+    - Weather: a console program that asynchronously downloads the Sydney
+               weather forecast and displays it.
+
+    - Conway:  a simulator for Conway's Game of Life with a Windows
+               Presentation Foundation GUI.  (Requires .NET 3.0 or later.)
+
+Requirements:
+
+  * GHC 6.8
+  
+    Salsa makes extensive use of type families and thus requires at least
+    version 6.8 of GHC.
+
+  * Microsoft .NET Framework 3.5
+
+    Since the Generator requires .NET 3.5, any Salsa development also requires
+    this version.  Executables produced with Salsa however will run with just
+    .NET 2.0 (provided that only .NET 2.0 assemblies are used by the program).
+
+    Salsa will not work with versions 1.0/1.1 of the .NET Framework, or with
+    Mono.  (Supporting Mono shouldn't be too much work though.)
+
+Building:
+
+  Build the Salsa library using Cabal (version 1.2) as usual:
+
+    runhaskell Setup.hs configure
+    runhaskell Setup.hs build
+    runhaskell Setup.hs install
+
+  The generator, driver, and each of the samples can be built with MSBuild;
+  just run 'msbuild' in the appropriate directory.  (The msbuild binary can be
+  found in '%WINDIR%\Microsoft.NET\Framework\v2.0.50272').
+
+Author:
+
+  Andrew Appleyard
+
diff --git a/Salsa.cabal b/Salsa.cabal
new file mode 100644
--- /dev/null
+++ b/Salsa.cabal
@@ -0,0 +1,70 @@
+Cabal-Version:  >= 1.2
+
+Name:           Salsa
+Version:        0.1.0.1
+Build-Type:     Simple
+
+Category:       Foreign
+Synopsis:       A .NET Bridge for Haskell
+Description:
+  Salsa is an experimental Haskell library and code generator that allows
+  Haskell programs to host the .NET runtime and interact with .NET libraries.
+  It uses type families extensively to provide a type-safe mapping of the .NET
+  object model in the Haskell type system.
+
+Author:         Andrew Appleyard
+Maintainer:     andrew.appleyard@gmail.com
+Homepage:       http://haskell.org/haskellwiki/Salsa
+
+License:        BSD3
+License-File:   LICENSE
+Copyright:      (c) 2007-2008 Andrew Appleyard
+
+Stability:      Experimental
+Tested-With:    GHC==6.8.3
+
+Extra-Source-Files:
+  README
+
+  Driver/README
+  Driver/Driver.proj
+  Driver/Driver.cs
+  Driver/Embed.hs
+
+  Generator/README
+  Generator/Generator.csproj
+  Generator/Generator.cs
+  Generator/Set.cs
+  Generator/Array.hs
+
+  Samples/Hello/Hello.proj
+  Samples/Hello/Hello.hs
+  Samples/Hello/Hello.imports
+
+  Samples/Weather/Weather.proj
+  Samples/Weather/Weather.hs
+  Samples/Weather/Weather.imports
+
+  Samples/Conway/Conway.proj
+  Samples/Conway/Conway.hs
+  Samples/Conway/Conway.imports
+  Samples/Conway/Conway.xaml
+
+  Docs/Thesis.pdf
+
+Library
+  Build-Depends: base, Win32, bytestring
+
+  Exposed-modules:
+    Foreign.Salsa
+    Foreign.Salsa.Binding
+
+  Other-Modules:
+    Foreign.Salsa.CLR, Foreign.Salsa.CLRHost, Foreign.Salsa.Common,
+    Foreign.Salsa.Core, Foreign.Salsa.Resolver, Foreign.Salsa.TypePrelude,
+    Foreign.Salsa.Driver
+
+  Extra-Libraries: oleaut32, ole32
+
+  Extensions: ForeignFunctionInterface
+
diff --git a/Samples/Conway/Conway.hs b/Samples/Conway/Conway.hs
new file mode 100644
--- /dev/null
+++ b/Samples/Conway/Conway.hs
@@ -0,0 +1,80 @@
+{-# LANGUAGE PatternSignatures, FlexibleContexts #-}
+module Main where
+
+import Foreign.Salsa
+import Bindings
+
+import Control.Monad
+import Data.Array
+import Data.Maybe
+
+loadXaml :: Coercible (Obj Object_) a => String -> IO a
+loadXaml xamlPath = do
+    uri <- new _Uri (xamlPath, _UriKind # _relative_)
+    streamInfo <- _Application # _getRemoteStream (uri)
+    xamlReader <- new _XamlReader ()
+    stream     <- get streamInfo _Stream
+    get streamInfo _Stream >>= \s -> xamlReader # _loadAsync s >>= cast
+
+-- | @'neighbors' states cell@ is the number of alive cells adjacent to @cell@ in @states@.
+neighbors :: Array (Int,Int) Bool -> (Int,Int) -> Int
+neighbors states (row,col) =
+    length $ filter (== True) [ states ! cell | cell <- neighborCells ]
+    where 
+        neighborCells = [ wrap (r,c) | r <- [row-1..row+1],
+                                       c <- [col-1..col+1],
+                                       wrap (r,c) /= (row,col) ]
+        wrap (r,c) = (r `mod` (maxRow+1), c `mod` (maxCol+1))
+        (_, (maxRow,maxCol)) = bounds states
+
+step :: Array (Int,Int) (Obj ToggleButton_) -> IO ()
+step buttons = do
+    buttonStates <- mapM (\b -> get b _IsChecked) (elems buttons)
+    let states = listArray (bounds buttons) (map fromJust buttonStates)
+    sequence_ $ do
+        cell <- indices states
+        let state' = case neighbors states cell of
+                        2         -> Nothing    -- unchanged
+                        3         -> Just True  -- comes to life
+                        otherwise -> Just False -- dies
+        case state' of
+            Nothing   -> mzero
+            otherwise -> return $ set (buttons ! cell) [ _IsChecked :== state' ]
+
+main :: IO ()
+main = withCLR $ do
+    win :: Obj Window_ <- loadXaml "/Conway.xaml"
+
+    -- Build an array of toggle buttons in 'grid'
+    grid :: Obj UniformGrid_ <- win # _findName ("grid") >>= cast
+    let (rows,cols) = (12,20)
+    set grid [_Columns :== fromIntegral cols]
+    buttonList <- sequence $ replicate (rows * cols) $ do
+        b <- new _ToggleButton ()
+        get grid _Children >>=# _add (b)
+        return b
+    let buttons = listArray ((0,0),(rows-1,cols-1)) buttonList
+
+    timer <- new _DispatcherTimer ()
+    set timer [_Tick     :+> delegate _EventHandler (\_ _ -> step buttons),
+               _Interval :=> _TimeSpan # _fromSeconds (0.1::Double)]
+
+    runButton :: Obj ToggleButton_ <- win # _findName ("runButton") >>= cast
+    set runButton [_Click :+> delegate _RoutedEventHandler
+        (\_ _ -> do Just run <- get runButton _IsChecked
+                    if run then timer # _start ()
+                           else timer # _stop ())]
+
+    clearButton :: Obj Button_ <- win # _findName ("clearButton") >>= cast
+    set clearButton [_Click :+> delegate _RoutedEventHandler
+        (\_ _ -> mapM_ (flip set [ _IsChecked :== Just False ]) (elems buttons))]
+        
+    exitButton :: Obj Button_ <- win # _findName ("exitButton") >>= cast
+    set exitButton [_Click :+> delegate _RoutedEventHandler (\_ _ -> win # _close_)]
+    
+    app <- new _Application ()
+    app # _run (win)
+
+    return ()
+
+-- vim:set sw=4 ts=4 expandtab:
diff --git a/Samples/Conway/Conway.imports b/Samples/Conway/Conway.imports
new file mode 100644
--- /dev/null
+++ b/Samples/Conway/Conway.imports
@@ -0,0 +1,49 @@
+reference C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll
+reference C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\PresentationCore.dll
+reference C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\PresentationFramework.dll 
+reference C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll
+
+System.Windows.Controls.Primitives.ToggleButton: IsChecked
+
+System.Windows.Threading.DispatcherTimer: Tick, Interval, Start, Stop, IsEnabled
+
+System.Uri
+System.UriKind: *
+System.Windows.Markup.XamlReader: LoadAsync
+System.Windows.Resources.StreamResourceInfo: Stream 
+
+System.Windows.Media.Pen
+System.Windows.Point
+System.Windows.Media.GeometryGroup: Children
+System.Windows.Media.Geometry
+System.Windows.Media.LineGeometry
+System.Windows.Media.EllipseGeometry: RadiusX, RadiusY
+System.Windows.Media.GeometryCollection: Add, Clear
+System.Windows.Media.RectangleGeometry
+System.Windows.Media.CombinedGeometry: GeometryCombineMode
+System.Windows.Media.GeometryDrawing: Geometry, Brush, Pen
+System.Windows.Media.DrawingImage: Freeze
+System.Windows.Controls.Image: Source, Stretch
+System.Windows.Media.Stretch: None
+System.Windows.Media.GeometryCombineMode: *
+System.Windows.Application: Run, GetRemoteStream
+System.Windows.Window: Title, Top, Close
+System.Windows.Controls.Button: Click
+System.Windows.Controls.Primitives.ToggleButton: Click
+System.Windows.Controls.ContentControl: Content
+System.Windows.Controls.StackPanel
+System.Windows.Controls.Primitives.UniformGrid: Columns
+System.Windows.Controls.Panel: Children
+System.Windows.Controls.UIElementCollection: Add
+System.Windows.Duration
+System.TimeSpan: FromSeconds
+System.Windows.Media.Colors: Red, Black
+System.Windows.Media.Brushes: Red, Black, Green
+System.Windows.Media.SolidColorBrush: ColorProperty
+System.Windows.Media.Animation.ColorAnimation
+System.Windows.Media.Animation.RepeatBehavior: Forever
+System.Windows.Media.Animation.Animatable: BeginAnimation
+System.Windows.Media.Animation.Timeline: AutoReverse, RepeatBehavior
+System.Windows.FrameworkElement: Width, Height, FindName
+System.Windows.Controls.Control: BackgroundProperty, Background
+System.Windows.RoutedEventHandler
diff --git a/Samples/Conway/Conway.proj b/Samples/Conway/Conway.proj
new file mode 100644
--- /dev/null
+++ b/Samples/Conway/Conway.proj
@@ -0,0 +1,49 @@
+﻿<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Module>Conway</Module>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Generate Include="$(Module).imports" />
+  </ItemGroup>
+  <ItemGroup>
+    <BindingFiles Include="Bindings.hs;Labels.hs" />
+  </ItemGroup>
+  <ItemGroup>
+    <IntermediateFiles Include="*.hi;*.o" />
+  </ItemGroup>
+
+  <!-- Build the 'Generator' program if necessary -->
+  <Target Name="BuildGenerator">
+    <MSBuild Projects="..\..\Generator\Generator.csproj"
+             ContinueOnError="false"
+             Properties="Configuration=Release">
+      <Output TaskParameter="TargetOutputs" ItemName="Generator" />
+    </MSBuild>
+  </Target>
+
+  <!-- Call 'Generator' to create the binding files from the import files -->
+  <Target Name="GenerateBindings" 
+          Inputs="@(Generate);@(Generator)"
+          Outputs="@(BindingFiles)"
+          DependsOnTargets="BuildGenerator">
+    <Exec Command="@(Generator) @(Generate)" />
+  </Target>
+
+  <!-- Run GHC to build the main program -->
+  <Target Name="Build"
+          DependsOnTargets="GenerateBindings">
+    <Exec Command="ghc --make $(Module) -fglasgow-exts -threaded" />
+  </Target>
+
+  <Target Name="Clean" >
+    <Delete Files="$(Module).exe" />
+    <Delete Files="$(Module).exe.manifest" />
+    <Delete Files="@(BindingFiles)" />
+    <Delete Files="@(BindingFiles -> '%(Filename)_stub.c')" />
+    <Delete Files="@(BindingFiles -> '%(Filename)_stub.h')" />
+    <Delete Files="@(IntermediateFiles)" />
+  </Target>
+
+  <Target Name="Rebuild" DependsOnTargets="Clean;Build" />
+</Project>
diff --git a/Samples/Conway/Conway.xaml b/Samples/Conway/Conway.xaml
new file mode 100644
--- /dev/null
+++ b/Samples/Conway/Conway.xaml
@@ -0,0 +1,59 @@
+<Window 
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+    Title="Game of Life" Width="424" Height="310">
+
+  <Window.Resources>
+    <LinearGradientBrush x:Key="alive">
+      <GradientStop Color="White" Offset="0.0" />
+      <GradientStop Color="Black" Offset="1.0" />
+    </LinearGradientBrush>
+    <RadialGradientBrush x:Key="dead">
+      <GradientStop Color="Transparent" Offset="0.0" />
+      <GradientStop Color="White"       Offset="0.1" />
+      <GradientStop Color="Transparent" Offset="0.1" />
+    </RadialGradientBrush>
+  </Window.Resources>
+
+  <Window.Background>
+    <LinearGradientBrush>
+      <GradientStop Color="White" Offset="0.0" />
+      <GradientStop Color="Gray" Offset="1.0" />
+    </LinearGradientBrush>
+  </Window.Background>
+
+  <DockPanel Margin="2">
+    <DockPanel DockPanel.Dock="Bottom" Margin="2" LastChildFill="False">
+      <ToggleButton Name="runButton" DockPanel.Dock="Left" Width="60"
+                    Margin="0,0,4,0" FontWeight="Bold">_Run!</ToggleButton>
+      <Button Name="clearButton" DockPanel.Dock="Left" Width="60">_Clear</Button>
+      <Button Name="exitButton" DockPanel.Dock="Right" Width="60">E_xit</Button>
+    </DockPanel>
+    <UniformGrid x:Name="grid" Margin="2">
+      <UniformGrid.Resources>
+        <Style TargetType="{x:Type ToggleButton}">
+          <Style.Triggers>
+            <Trigger Property="ToggleButton.IsChecked" Value="True">
+              <Setter Property="Background" Value="White" />
+              <Setter Property="Foreground" Value="{StaticResource alive}" />
+            </Trigger>
+          </Style.Triggers>
+          <Setter Property="Foreground" Value="Transparent" />
+          <Setter Property="Background" Value="{StaticResource dead}" />
+          <Setter Property="Template">
+            <Setter.Value>
+              <ControlTemplate>
+                <Rectangle Fill="{TemplateBinding Background}"
+                           Stroke="{TemplateBinding Foreground}"
+                           RadiusX="2" RadiusY="2"
+                           Margin="1" />
+              </ControlTemplate>
+            </Setter.Value>
+          </Setter>
+        </Style>
+      </UniformGrid.Resources>
+      <!-- Insert ToggleButton's in Haskell code -->
+    </UniformGrid>
+  </DockPanel>
+</Window>
+<!-- vim:set ts=2 sw=2 expandtab syntax=xml: -->
diff --git a/Samples/Hello/Hello.hs b/Samples/Hello/Hello.hs
new file mode 100644
--- /dev/null
+++ b/Samples/Hello/Hello.hs
@@ -0,0 +1,14 @@
+module Main where
+
+--
+-- Displays 'Hello .NET World!' using .NET's Console.WriteLine() method.
+--
+
+import Foreign.Salsa
+import Bindings
+
+main :: IO ()
+main = withCLR $ do
+    _Console # _writeLine ("Hello .NET World!")
+
+-- vim:set sw=4 ts=4 expandtab:
diff --git a/Samples/Hello/Hello.imports b/Samples/Hello/Hello.imports
new file mode 100644
--- /dev/null
+++ b/Samples/Hello/Hello.imports
@@ -0,0 +1,2 @@
+reference C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll
+System.Console: WriteLine
diff --git a/Samples/Hello/Hello.proj b/Samples/Hello/Hello.proj
new file mode 100644
--- /dev/null
+++ b/Samples/Hello/Hello.proj
@@ -0,0 +1,49 @@
+﻿<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Module>Hello</Module>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Generate Include="$(Module).imports" />
+  </ItemGroup>
+  <ItemGroup>
+    <BindingFiles Include="Bindings.hs;Labels.hs" />
+  </ItemGroup>
+  <ItemGroup>
+    <IntermediateFiles Include="*.hi;*.o" />
+  </ItemGroup>
+
+  <!-- Build the 'Generator' program if necessary -->
+  <Target Name="BuildGenerator">
+    <MSBuild Projects="..\..\Generator\Generator.csproj"
+             ContinueOnError="false"
+             Properties="Configuration=Release">
+      <Output TaskParameter="TargetOutputs" ItemName="Generator" />
+    </MSBuild>
+  </Target>
+
+  <!-- Call 'Generator' to create the binding files from the import files -->
+  <Target Name="GenerateBindings" 
+          Inputs="@(Generate);@(Generator)"
+          Outputs="@(BindingFiles)"
+          DependsOnTargets="BuildGenerator">
+    <Exec Command="@(Generator) @(Generate)" />
+  </Target>
+
+  <!-- Run GHC to build the main program -->
+  <Target Name="Build"
+          DependsOnTargets="GenerateBindings">
+    <Exec Command="ghc --make $(Module) -fglasgow-exts -threaded" />
+  </Target>
+
+  <Target Name="Clean" >
+    <Delete Files="$(Module).exe" />
+    <Delete Files="$(Module).exe.manifest" />
+    <Delete Files="@(BindingFiles)" />
+    <Delete Files="@(BindingFiles -> '%(Filename)_stub.c')" />
+    <Delete Files="@(BindingFiles -> '%(Filename)_stub.h')" />
+    <Delete Files="@(IntermediateFiles)" />
+  </Target>
+
+  <Target Name="Rebuild" DependsOnTargets="Clean;Build" />
+</Project>
diff --git a/Samples/Weather/Weather.hs b/Samples/Weather/Weather.hs
new file mode 100644
--- /dev/null
+++ b/Samples/Weather/Weather.hs
@@ -0,0 +1,61 @@
+module Main where
+
+--
+-- Asynchronously downloads the Sydney weather forecast from the Australian
+-- Bureau of Meterology FTP site (using a worker thread) and displays the
+-- result.  A progress indicator is displayed during the download.
+--
+
+import Control.Concurrent.MVar
+import Control.Monad
+import System.IO
+
+import Foreign.Salsa
+import Bindings
+
+main :: IO ()
+main = withCLR $ do
+    hSetBuffering stdout NoBuffering
+
+    -- Make an MVar to hold the result of the download when it has completed
+    done <- newEmptyMVar 
+
+    -- Create a delegate that accepts a single argument and puts it into the
+    -- MVar when called
+    finished <- delegate _ParameterizedThreadStart (putMVar done)
+
+    -- Instantiate a WebClient for downloading the weather forecast, and set
+    -- the DownloadStringCompleted event to the @downloaded@ function.
+    client <- new _WebClient ()
+    set client [ _DownloadStringCompleted :+> delegate _DownloadStringCompletedEventHandler downloaded ]
+
+    -- Download the weather forecast asynchronously, using the @finished@
+    -- delegate as user state for the handler.
+    uri <- new _Uri ("ftp://ftp2.bom.gov.au/anon/gen/fwo/IDN10064.txt")
+    client # _downloadStringAsync (uri, cast finished :: Obj Object_)
+
+    putStr "Downloading... |"
+
+    -- Display an animated progress indicator until the MVar is filled
+    let wait (c:cs) = do putStr ('\b':[c])
+                         _Thread # _sleep (250 :: Int32)
+                         isNotDone <- isEmptyMVar done
+                         when isNotDone $ wait (cs ++ [c])
+                         putStr "\b \n"
+    wait "/-\\|"
+
+    -- Display the result from the MVar
+    s <- takeMVar done
+    s # _toString () >>= putStrLn
+
+downloaded :: Obj Object_ -> Obj DownloadStringCompletedEventArgs_ -> IO ()
+downloaded _ e = do
+    -- Get the result object (it will be a .NET string instance), and the
+    -- finished object delegate (it will be a .NET delegate instance)
+    result   <- get e _Result
+    finished <- get e _UserState 
+
+    -- Invoke the finished delegate, passing it the result
+    (cast $ finished :: Obj ParameterizedThreadStart_) # _invoke result
+    
+-- vim:set sw=4 ts=4 expandtab:
diff --git a/Samples/Weather/Weather.imports b/Samples/Weather/Weather.imports
new file mode 100644
--- /dev/null
+++ b/Samples/Weather/Weather.imports
@@ -0,0 +1,8 @@
+reference C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll
+System.Console: WriteLine
+System.Net.WebClient: DownloadStringAsync, DownloadStringCompleted, DownloadString, DownloadStringCompletedEventHandler
+System.Net.DownloadStringCompletedEventArgs: Result, UserState
+System.Uri
+System.Threading.Thread: Sleep
+System.Threading.ParameterizedThreadStart: Invoke
+System.Object: ToString
diff --git a/Samples/Weather/Weather.proj b/Samples/Weather/Weather.proj
new file mode 100644
--- /dev/null
+++ b/Samples/Weather/Weather.proj
@@ -0,0 +1,49 @@
+﻿<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Module>Weather</Module>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Generate Include="$(Module).imports" />
+  </ItemGroup>
+  <ItemGroup>
+    <BindingFiles Include="Bindings.hs;Labels.hs" />
+  </ItemGroup>
+  <ItemGroup>
+    <IntermediateFiles Include="*.hi;*.o" />
+  </ItemGroup>
+
+  <!-- Build the 'Generator' program if necessary -->
+  <Target Name="BuildGenerator">
+    <MSBuild Projects="..\..\Generator\Generator.csproj"
+             ContinueOnError="false"
+             Properties="Configuration=Release">
+      <Output TaskParameter="TargetOutputs" ItemName="Generator" />
+    </MSBuild>
+  </Target>
+
+  <!-- Call 'Generator' to create the binding files from the import files -->
+  <Target Name="GenerateBindings" 
+          Inputs="@(Generate);@(Generator)"
+          Outputs="@(BindingFiles)"
+          DependsOnTargets="BuildGenerator">
+    <Exec Command="@(Generator) @(Generate)" />
+  </Target>
+
+  <!-- Run GHC to build the main program -->
+  <Target Name="Build"
+          DependsOnTargets="GenerateBindings">
+    <Exec Command="ghc --make $(Module) -fglasgow-exts -threaded" />
+  </Target>
+
+  <Target Name="Clean" >
+    <Delete Files="$(Module).exe" />
+    <Delete Files="$(Module).exe.manifest" />
+    <Delete Files="@(BindingFiles)" />
+    <Delete Files="@(BindingFiles -> '%(Filename)_stub.c')" />
+    <Delete Files="@(BindingFiles -> '%(Filename)_stub.h')" />
+    <Delete Files="@(IntermediateFiles)" />
+  </Target>
+
+  <Target Name="Rebuild" DependsOnTargets="Clean;Build" />
+</Project>
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
