/*
 * Default.cs --
 *
 * Copyright (c) 2007-2012 by Joe Mistachkin.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: $
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;

#if NETWORK
using System.Net;
#endif

using System.Reflection;
using System.Runtime.InteropServices;

#if SERIALIZATION
using System.Runtime.Serialization;
#endif

#if REMOTING
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
#endif

#if CAS_POLICY
using System.Security.Policy;
#endif

#if NETWORK && REMOTING
using System.Security.Principal;
#endif

using System.Text.RegularExpressions;
using System.Threading;
using Eagle._Attributes;
using Eagle._Components.Private;
using Eagle._Components.Public;
using Eagle._Components.Public.Delegates;
using Eagle._Constants;
using Eagle._Containers.Private;
using Eagle._Containers.Public;
using Eagle._Interfaces.Private;
using Eagle._Interfaces.Public;

#if !CONSOLE
using ConsoleColor = Eagle._Components.Public.ConsoleColor;
#endif

namespace Eagle._Tests
{
    [ObjectId("e1257294-a012-4164-b0ea-3763dd06eec2")]
    public class Default : IDisposable
    {
        #region Private Constants
        private static readonly string TestCustomInfoBoxName = "TestCustomInfo";
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private Delegates
        [ObjectId("13daa524-57d2-470e-b67d-23490b21e0d0")]
        private delegate void VoidWithStringCallback(string value);

        [ObjectId("ad67563c-a83c-4cb4-a91b-aaed767f57a0")]
        private delegate long LongWithDateTimeCallback(DateTime dateTime);

        [ObjectId("c3cb55e9-3e8f-4e0d-95ec-d2b324f36715")]
        private delegate IEnumerable IEnumerableWithICommandCallback(ICommand command);
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Public Constructors
        public Default()
        {
            @event = ThreadOps.CreateEvent(false);
            intArrayField = new int[10];
            privateField = this.ToString();
            intPtrArrayField = Array.CreateInstance(typeof(IntPtr), new int[] { 2, 3 });
            objectArrayField = Array.CreateInstance(typeof(Default), new int[] { 1 });
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public Default(sbyte test)
            : this()
        {
            internalField = test;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private Static Data
        private static Type staticTypeField;
        private static object staticObjectField;
        private static StringPairList customInfoList;
        private static ObjectWrapperDictionary savedObjects;
        private static DateTime now;
        private static DateTimeNowCallback nowCallback;
        private static long nowIncrement;
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private Data
        private EventWaitHandle @event;
        private Result asyncResult;
        public int[] intArrayField;
        internal sbyte internalField;
        public bool boolField;
        public byte byteField;
        public short shortField;
        public int intField;
        public long longField;
        public decimal decimalField;
        private string privateField;
        private Type typeField;
        private object objectField;
        private Array intPtrArrayField;
        private Array objectArrayField;
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Public Static Methods
        public static int TestMethod(
            string argument /* This is the value of the "pwzArgument" argument
                             * as it was passed to native CLR API method
                             * ICLRRuntimeHost.ExecuteInDefaultAppDomain. */
            )
        {
            int value = 0;

            if (Value.GetInteger2(
                    argument, ValueFlags.AnyInteger, null,
                    ref value) == ReturnCode.Ok)
            {
                return value;
            }

            return -1;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static void TestSetQuiet(
            Interpreter interpreter,
            bool quiet
            )
        {
            if (interpreter == null)
                return;

            interpreter.Quiet = quiet;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static void TestSetNoBackgroundError(
            Interpreter interpreter,
            bool noBackgroundError
            )
        {
            if (interpreter == null)
                return;

            interpreter.SetNoBackgroundError(noBackgroundError);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestSetComplain(
            Interpreter interpreter,
            bool complain
            )
        {
            if (interpreter == null)
                return false;

            IInteractiveHost interactiveHost = interpreter.Host;

            if (interactiveHost == null)
                return false;

            FieldInfo fieldInfo = interactiveHost.GetType().GetField(
                "hostFlags", BindingFlags.Instance | BindingFlags.NonPublic |
                BindingFlags.GetField);

            if (fieldInfo == null)
                return false;

            HostFlags hostFlags = (HostFlags)fieldInfo.GetValue(
                interactiveHost);

            if (complain)
                hostFlags |= HostFlags.Complain;
            else
                hostFlags &= ~HostFlags.Complain;

            fieldInfo.SetValue(interactiveHost, hostFlags);
            return true;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if SHELL
        public static ExitCode TestShellMainCore(
            Interpreter interpreter,
            IEnumerable<string> args,
            bool initialize,
            bool loop,
            ref Result result
            )
        {
            return Interpreter.ShellMainCore(
                interpreter, TestShellArgumentCallback, null, null, null,
                null, null, args, initialize, loop, ref result);
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestLoadPluginViaBytes(
            Interpreter interpreter,
            string assemblyFileName,
#if CAS_POLICY
            Evidence evidence,
#endif
            string typeName,
            IClientData clientData,
            PluginFlags pluginFlags,
            ref IPlugin plugin,
            ref long token,
            ref Result result
            )
        {
            if (interpreter == null)
            {
                result = "invalid interpreter";
                return ReturnCode.Error;
            }

            if (String.IsNullOrEmpty(assemblyFileName))
            {
                result = "invalid assembly file name";
                return ReturnCode.Error;
            }

            if (!File.Exists(assemblyFileName))
            {
                result = String.Format(
                    "cannot load plugin: assembly file \"{0}\" does not exist",
                    assemblyFileName);

                return ReturnCode.Error;
            }

            if (plugin != null)
            {
                result = "cannot overwrite valid plugin";
                return ReturnCode.Error;
            }

            if (token != 0)
            {
                result = "cannot overwrite valid plugin token";
                return ReturnCode.Error;
            }

            ReturnCode code = ReturnCode.Ok;

            try
            {
                //
                // NOTE: Figure out what the debug symbols file for the
                //       assembly would be if it actually existed.
                //
                string symbolFileName = Path.Combine(Path.GetDirectoryName(
                    assemblyFileName), Path.GetFileNameWithoutExtension(
                    assemblyFileName) + FileExtension.Symbols); /* throw */

                byte[] assemblyBytes = File.ReadAllBytes(
                    assemblyFileName); /* throw */

                byte[] symbolBytes = File.Exists(symbolFileName) ?
                    File.ReadAllBytes(symbolFileName) : null; /* throw */

                code = interpreter.LoadPlugin(assemblyBytes, symbolBytes,
#if CAS_POLICY
                    evidence,
#endif
                    typeName, clientData, pluginFlags, ref plugin, ref result);

                if (code == ReturnCode.Ok)
                {
                    code = interpreter.AddPlugin(
                        plugin, clientData, ref token, ref result);
                }

                return code;
            }
            catch (Exception e)
            {
                result = e;
            }
            finally
            {
                if ((code != ReturnCode.Ok) && (plugin != null))
                {
                    ReturnCode unloadCode;
                    Result unloadResult = null;

                    unloadCode = interpreter.UnloadPlugin(
                        plugin, clientData, pluginFlags, ref unloadResult);

                    if (unloadCode != ReturnCode.Ok)
                        DebugOps.Complain(interpreter, unloadCode, unloadResult);
                }
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestRenameNamespace(
            Interpreter interpreter,
            string oldName,
            string newName,
            ref Result error
            )
        {
            if (String.IsNullOrEmpty(newName))
            {
                error = "invalid or empty new namespace name";
                return ReturnCode.Error;
            }

            if (NamespaceOps.IsQualifiedName(newName))
            {
                error = "new namespace name must not be qualified";
                return ReturnCode.Error;
            }

            INamespace @namespace = NamespaceOps.Lookup(
                interpreter, oldName, false, false, ref error);

            if (@namespace == null)
                return ReturnCode.Error;

            try
            {
                @namespace.Name = newName;
                return ReturnCode.Ok;
            }
            catch (Exception e)
            {
                error = e;
                return ReturnCode.Error;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static void TestSaveObjects(
            Interpreter interpreter
            )
        {
            if (interpreter == null)
                return;

            interpreter.SaveObjects(ref savedObjects);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static void TestRestoreObjects(
            Interpreter interpreter
            )
        {
            if (interpreter == null)
                return;

            interpreter.RestoreObjects(ref savedObjects);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static void TestExecuteDelegateCommands(
            Interpreter interpreter,
            ArgumentList arguments,
            bool dynamic,
            ref ReturnCodeList returnCodes,
            ref ResultList results
            )
        {
            if (returnCodes == null)
                returnCodes = new ReturnCodeList();

            if (results == null)
                results = new ResultList();

            long[] tokens = { 0, 0, 0 };

            try
            {
                ReturnCode code;
                Result result = null;

                if (interpreter == null)
                {
                    returnCodes.Add(ReturnCode.Error);
                    results.Add("invalid interpreter");

                    return;
                }

                if (arguments == null)
                {
                    returnCodes.Add(ReturnCode.Error);
                    results.Add("invalid argument list");

                    return;
                }

                IPlugin plugin =
#if DEBUG
                    interpreter.GetTestPlugin(ref result);
#else
                    interpreter.GetCorePlugin(ref result);
#endif

                if (plugin == null)
                {
                    returnCodes.Add(ReturnCode.Error);
                    results.Add(result);

                    return;
                }

                Delegate[] delegates = { null, null, null };

                if (dynamic)
                {
                    MethodInfo[] methodInfo = { null, null, null };

                    methodInfo[0] = typeof(Default).GetMethod(
                        "TestVoidMethod",
                        BindingFlags.Static | BindingFlags.NonPublic);

                    if (methodInfo[0] == null)
                    {
                        returnCodes.Add(ReturnCode.Error);
                        results.Add("method TestVoidMethod not found");

                        return;
                    }

                    methodInfo[1] = typeof(Default).GetMethod(
                        "TestLongMethod",
                        BindingFlags.Static | BindingFlags.NonPublic);

                    if (methodInfo[1] == null)
                    {
                        returnCodes.Add(ReturnCode.Error);
                        results.Add("method TestLongMethod not found");

                        return;
                    }

                    methodInfo[2] = typeof(Default).GetMethod(
                        "TestIEnumerableMethod",
                        BindingFlags.Static | BindingFlags.NonPublic);

                    if (methodInfo[2] == null)
                    {
                        returnCodes.Add(ReturnCode.Error);
                        results.Add("method TestIEnumerableMethod not found");

                        return;
                    }

                    Type[] types = { null, null, null };

                    code = DelegateOps.CreateManagedDelegateType(
                        interpreter, null, null, null, null,
                        methodInfo[0].ReturnType,
                        GetParameterTypeList(methodInfo[0]), ref types[0],
                        ref result);

                    if (code != ReturnCode.Ok)
                    {
                        returnCodes.Add(code);
                        results.Add(result);

                        return;
                    }

                    code = DelegateOps.CreateManagedDelegateType(
                        interpreter, null, null, null, null,
                        methodInfo[1].ReturnType,
                        GetParameterTypeList(methodInfo[1]), ref types[1],
                        ref result);

                    if (code != ReturnCode.Ok)
                    {
                        returnCodes.Add(code);
                        results.Add(result);

                        return;
                    }

                    code = DelegateOps.CreateManagedDelegateType(
                        interpreter, null, null, null, null,
                        methodInfo[2].ReturnType,
                        GetParameterTypeList(methodInfo[2]), ref types[2],
                        ref result);

                    if (code != ReturnCode.Ok)
                    {
                        returnCodes.Add(code);
                        results.Add(result);

                        return;
                    }

                    delegates[0] = Delegate.CreateDelegate(types[0],
                        methodInfo[0], false);

                    delegates[1] = Delegate.CreateDelegate(types[1],
                        methodInfo[1], false);

                    delegates[2] = Delegate.CreateDelegate(types[2],
                        methodInfo[2], false);
                }
                else
                {
                    delegates[0] = new VoidWithStringCallback(
                        TestVoidMethod);

                    delegates[1] = new LongWithDateTimeCallback(
                        TestLongMethod);

                    delegates[2] = new IEnumerableWithICommandCallback(
                        TestIEnumerableMethod);
                }

                ICommand[] commands = { null, null, null };

                commands[0] = new _Commands._Delegate(new CommandData(
                    "voidDelegate", null, null, ClientData.Empty,
                    typeof(_Commands._Delegate).FullName, CommandFlags.None,
                    plugin, 0), new DelegateData(delegates[0], false, 0));

                commands[1] = new _Commands._Delegate(new CommandData(
                    "longDelegate", null, null, ClientData.Empty,
                    typeof(_Commands._Delegate).FullName, CommandFlags.None,
                    plugin, 0), new DelegateData(delegates[1], false, 0));

                commands[2] = new _Commands._Delegate(new CommandData(
                    "enumerableDelegate", null, null, ClientData.Empty,
                    typeof(_Commands._Delegate).FullName, CommandFlags.None,
                    plugin, 0), new DelegateData(delegates[2], false, 0));

                code = interpreter.AddCommand(
                    commands[0], ClientData.Empty, ref tokens[0],
                    ref result);

                if (code != ReturnCode.Ok)
                {
                    returnCodes.Add(code);
                    results.Add(result);

                    return;
                }

                code = interpreter.AddCommand(
                    commands[1], ClientData.Empty, ref tokens[1],
                    ref result);

                if (code != ReturnCode.Ok)
                {
                    returnCodes.Add(code);
                    results.Add(result);

                    return;
                }

                code = interpreter.AddCommand(
                    commands[2], ClientData.Empty, ref tokens[2],
                    ref result);

                if (code != ReturnCode.Ok)
                {
                    returnCodes.Add(code);
                    results.Add(result);

                    return;
                }

                arguments.Insert(0, commands[0].Name);

                code = Engine.EvaluateScript(interpreter, arguments.ToString(),
                    ref result);

                returnCodes.Add(code);
                results.Add(result);

                arguments[0] = commands[1].Name;

                code = Engine.EvaluateScript(interpreter, arguments.ToString(),
                    ref result);

                returnCodes.Add(code);
                results.Add(result);

                arguments[0] = commands[2].Name;

                code = Engine.EvaluateScript(interpreter, arguments.ToString(),
                    ref result);

                returnCodes.Add(code);
                results.Add(result);
            }
            finally
            {
                if (interpreter != null)
                {
                    ReturnCode removeCode;
                    Result removeError = null;

                    if (tokens[2] != 0)
                    {
                        removeCode = interpreter.RemoveCommand(
                            tokens[2], null, ref removeError);

                        if (removeCode != ReturnCode.Ok)
                        {
                            DebugOps.Complain(
                                interpreter, removeCode, removeError);
                        }
                    }

                    if (tokens[1] != 0)
                    {
                        removeCode = interpreter.RemoveCommand(
                            tokens[1], null, ref removeError);

                        if (removeCode != ReturnCode.Ok)
                        {
                            DebugOps.Complain(
                                interpreter, removeCode, removeError);
                        }
                    }

                    if (tokens[0] != 0)
                    {
                        removeCode = interpreter.RemoveCommand(
                            tokens[0], null, ref removeError);

                        if (removeCode != ReturnCode.Ok)
                        {
                            DebugOps.Complain(
                                interpreter, removeCode, removeError);
                        }
                    }
                }
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static void TestExecuteStaticDelegates(
            ArgumentList arguments,
            ref ReturnCodeList returnCodes,
            ref ResultList results
            )
        {
            if (returnCodes == null)
                returnCodes = new ReturnCodeList();

            if (results == null)
                results = new ResultList();

            ReturnCode code;
            Result result = null;

            code = Engine.ExecuteDelegate(
                new VoidWithStringCallback(TestVoidMethod),
                arguments, ref result);

            returnCodes.Add(code);
            results.Add(result);

            code = Engine.ExecuteDelegate(
                new LongWithDateTimeCallback(TestLongMethod),
                arguments, ref result);

            returnCodes.Add(code);
            results.Add(result);

            code = Engine.ExecuteDelegate(
                new IEnumerableWithICommandCallback(TestIEnumerableMethod),
                arguments, ref result);

            returnCodes.Add(code);
            results.Add(result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestToIntPtr(
            Interpreter interpreter,  /* NOT USED */
            Type type,                /* NOT USED */
            string text,
            OptionDictionary options, /* NOT USED */
            CultureInfo cultureInfo,
            IClientData clientData,   /* NOT USED */
            ref object value,
            ref Result error
            )
        {
            long longValue = 0;

            if (Value.GetWideInteger2(
                    text, ValueFlags.AnyWideInteger, cultureInfo,
                    ref longValue, ref error) != ReturnCode.Ok)
            {
                return ReturnCode.Error;
            }

            //
            // HACK: Maybe truncate 64-bit pointer value to 32-bit.
            //
            if (PlatformOps.Is64BitProcess())
                value = new IntPtr(longValue);
            else
                value = new IntPtr(ConversionOps.ToInt(longValue));

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestIntPtrChangeTypeCallback(
            Interpreter interpreter,
            bool install,
            ref Result error
            )
        {
            if (interpreter == null)
            {
                error = "invalid interpreter";
                return ReturnCode.Error;
            }

            IScriptBinder scriptBinder = interpreter.Binder as IScriptBinder;

            if (scriptBinder == null)
            {
                error = "invalid script binder";
                return ReturnCode.Error;
            }

            if (install)
            {
                if (scriptBinder.AddChangeTypeCallback(
                        typeof(IntPtr), TestToIntPtr,
                        ref error) != ReturnCode.Ok)
                {
                    return ReturnCode.Error;
                }
            }
            else
            {
                if (scriptBinder.RemoveChangeTypeCallback(
                        typeof(IntPtr), ref error) != ReturnCode.Ok)
                {
                    return ReturnCode.Error;
                }
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static string TestToHexadecimalString(
            byte[] array
            )
        {
            return ArrayOps.ToHexadecimalString(array);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static MethodInfo TestMethodInfo()
        {
            return typeof(Default).GetMethod("TestMethodInfo");
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ChangeTypeCallback TestReturnChangeTypeCallback()
        {
            return TestChangeTypeCallback;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ToStringCallback TestReturnToStringCallback()
        {
            return TestToStringCallback;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestChangeTypeCallback(
            Interpreter interpreter,
            Type type,
            string text,
            OptionDictionary options,
            CultureInfo cultureInfo,
            IClientData clientData,
            ref object value,
            ref Result error
            )
        {
            value = text;

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestToStringCallback(
            Interpreter interpreter,
            Type type,
            object value,
            OptionDictionary options,
            CultureInfo cultureInfo,
            IClientData clientData,
            ref string text,
            ref Result error
            )
        {
            text = (value != null) ? value.ToString() : String.Empty;

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static void StaticMethodWithDelegate(
            GetTypeCallback callback
            )
        {
            // do nothing.
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static object TestIdentity(
            object arg
            )
        {
            return MarshalOps.Identity(arg);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestStringArray(
            string [] array
            )
        {
            return true;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestArray(
            int[] array
            )
        {
            return true;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static int TestNullArray(
            int[] array
            )
        {
            if (array == null)
                return -1;

            int count = 0;

            foreach (int element in array)
                count += element;

            return count;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestObjectAsArray(
            object input,
            ref object output
            )
        {
            output = new object[] { input, output };
            return (input != null);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestOutArray(
            bool create,
            out int[] array
            )
        {
            if (create)
                array = new int[] { 1, 2, 3 };
            else
                array = null;

            return true;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestMulti2Array(
            int[,] array
            )
        {
            return true;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestMulti3Array(
            int[, ,] array
            )
        {
            return true;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestNestedArray(
            int[][] array
            )
        {
            return true;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static sbyte TestSByte(
            byte X
            )
        {
            return ConversionOps.ToSByte(X);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static int TestInt(
            uint X
            )
        {
            return ConversionOps.ToInt(X);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static long TestLong(
            ulong X
            )
        {
            return ConversionOps.ToLong(X);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ulong TestULong(
            long X
            )
        {
            return ConversionOps.ToULong(X);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestIntParams(
            params int[] args
            )
        {
            return true;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestEnum(
            ReturnCode x
            )
        {
            return (x == ReturnCode.Ok);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestByRefEnum(
            ref ReturnCode x
            )
        {
            if (x == ReturnCode.Error)
                x = ReturnCode.Break;

            return (x == ReturnCode.Ok);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestNullableEnum(
            ReturnCode? x
            )
        {
            return (x != null);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestByRefNullableEnum(
            ref ReturnCode? x
            )
        {
            if ((x != null) && (x == ReturnCode.Error))
                x = ReturnCode.Break;

            return (x != null);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ByteList TestByteList()
        {
            return new ByteList(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static IntList TestIntList()
        {
            return new IntList(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static LongList TestLongList()
        {
            return new LongList(new long[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static DerivedList TestDerivedList()
        {
            return new DerivedList();
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static StringDictionary TestStringDictionary(
            bool enumerable,
            bool keys,
            bool values,
            params string[] args
            )
        {
            if (enumerable)
                return new StringDictionary((IEnumerable<string>)args, keys, values);
            else
                return new StringDictionary(new StringList(args), keys, values);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static StringPairList TestStringPairList(
            Interpreter interpreter
            )
        {
            Result error = null;

            return AttributeOps.GetObjectIds(
                (interpreter != null) ? interpreter.GetAppDomain() : null, true, ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static StringPairList[] TestArrayOfStringPairList()
        {
            return new StringPairList[] {
                new StringPairList(
                    new StringPair(),
                    new StringPair("this is a test #1."),
                    new StringPair("1", "2"),
                    new StringPair("3", "4"),
                    new StringPair("5", "6"),
                    new StringPair("7", "8"),
                    new StringPair("9", "10")),
                new StringPairList(
                    new StringPair(),
                    new StringPair("this is a test #2."),
                    new StringPair("11", "12"),
                    new StringPair("13", "14"),
                    new StringPair("15", "16"),
                    new StringPair("17", "18"),
                    new StringPair("19", "20"))
            };
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static Guid TestObjectId(
            Interpreter interpreter
            )
        {
            // ICommand command = null;
            // Result error = null;

            // interpreter.GetCommand("apply", false, true, ref command, ref error);
            // interpreter.GetCommand("apply", true, true, ref command, ref error);

            Guid id = AttributeOps.GetObjectId(typeof(ObjectIdAttribute));

            IInteractiveHost interactiveHost =
                (interpreter != null) ? interpreter.Host : null;

            if (interactiveHost != null)
                interactiveHost.Write(id.ToString());

            return id;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestSetDateTimeNowCallback(
            Interpreter interpreter,
            DateTime dateTime,
            long increment,
            bool enable
            )
        {
            if (interpreter == null)
                return false;

            IEventManager eventManager = interpreter.EventManager;

            if (eventManager == null)
                return false;

            if (enable)
            {
                now = dateTime;
                nowCallback = eventManager.NowCallback; /* save */
                nowIncrement = increment;
                eventManager.NowCallback = TestDateTimeNow; /* set */
            }
            else
            {
                now = DateTime.MinValue;
                eventManager.NowCallback = nowCallback; /* restore */
                nowCallback = null; /* clear */
                nowIncrement = 0;
            }

            return true;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static StringList TestStringListFromString(
            string value
            )
        {
            return StringList.FromString(value);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NATIVE && WINDOWS
        public static bool TestPeInformation(
            string fileName,
            ref uint timeStamp,
            ref UIntPtr reserve,
            ref UIntPtr commit
            )
        {
            return FileOps.GetPeFileTimeStamp(fileName, ref timeStamp) &&
                FileOps.GetPeFileStackReserveAndCommit(fileName, ref reserve, ref commit);
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static string TestResource(
            Interpreter interpreter
            )
        {
            return ResourceOps.GetString(
                interpreter, ResourceId.Test, 1, TimeOps.GetUtcNow(), "test");
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static void TestScriptStream(
            Interpreter interpreter,
            string value,
            int length,
            ref Result result
            )
        {
            if (interpreter == null)
                return;

#if false
            IInteractiveHost interactiveHost = interpreter.Host;
#endif

            if (value == null) /* NOTE: Default? */
            {
                value = "set x 1" + Characters.DosNewLine +
                    Characters.EndOfFile + "abc";
            }

            ReturnCode[] code = { ReturnCode.Ok, ReturnCode.Ok };
            Result[] localResult = { null, null };
            string[] extra = { null, null };

            using (StringReader stringReader = new StringReader(value))
            {
                EngineFlags engineFlags = EngineFlags.ForceSoftEof;
                string text = null;

                code[0] = Engine.ReadScriptStream(
                    interpreter, null, stringReader, 0,
                    length, ref engineFlags, ref text,
                    ref localResult[0]);

                if (code[0] == ReturnCode.Ok)
                    localResult[0] = text;

                extra[0] = stringReader.ReadToEnd();
            }

#if false
            if (interactiveHost != null)
                interactiveHost.WriteResultLine(code[0], localResult[0]);

            if (interactiveHost != null)
                interactiveHost.WriteResultLine(code[0], extra[0]);

            using (StringReader stringReader = new StringReader(value))
            {
                EngineFlags engineFlags = EngineFlags.ForceSoftEof;
                string text = null;

                code[1] = Engine.ReadScriptStream(
                    interpreter, null, stringReader, 0,
                    Count.Invalid, ref engineFlags, ref text,
                    ref localResult[1]);

                if (code[1] == ReturnCode.Ok)
                    localResult[1] = text;

                extra[1] = stringReader.ReadToEnd();
            }

            if (interactiveHost != null)
                interactiveHost.WriteResultLine(code[1], localResult[1]);

            if (interactiveHost != null)
                interactiveHost.WriteResultLine(code[1], extra[1]);
#endif

            result = StringList.MakeList(code[0], code[1], localResult[0],
                localResult[1], extra[0], extra[1]);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestSubstituteFile(
            Interpreter interpreter,
            string fileName,
            EngineFlags engineFlags,
            SubstitutionFlags substitutionFlags,
            EventFlags eventFlags,
            ExpressionFlags expressionFlags,
            ref Result result
            )
        {
            ReturnCode code = Engine.SubstituteFile(
                interpreter, fileName, engineFlags,
                substitutionFlags, eventFlags, expressionFlags,
                ref result);

            IInteractiveHost interactiveHost = interpreter.Host;

            if (interactiveHost != null)
                interactiveHost.WriteResultLine(code, result);

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestMatchComparer(
            MatchMode mode,
            bool noCase,
            RegexOptions regExOptions,
            StringList list,
            string value,
            ref bool match,
            ref Result error
            )
        {
            if (list != null)
            {
                if (value != null)
                {
                    try
                    {
                        PathDictionary<int> paths = new PathDictionary<int>(
                            new _Comparers.Match(mode, noCase, regExOptions));

                        paths.Add(list);
                        match = paths.ContainsKey(value);

                        return ReturnCode.Ok;
                    }
                    catch (Exception e)
                    {
                        error = e;
                    }
                }
                else
                {
                    error = "invalid value";
                }
            }
            else
            {
                error = "invalid list";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestExpr( /* LOCAL-ONLY */
            Interpreter interpreter,
            string text,
            ref bool usable,
            ref bool exception,
            ref Result result,
            out Result result2
            )
        {
            ReturnCode code;

            IParseState parseState = new ParseState(interpreter.SubstitutionFlags);

            result2 = null;

            code = ExpressionParser.ParseExpression(
                interpreter, text, 0,
                (text != null) ? text.Length : 0,
                parseState, true, ref result2);

            if (code != ReturnCode.Ok)
            {
                result.Value = result2;
                return code;
            }

            Argument value = null;
            Result error = null;

            code = ExpressionEvaluator.EvaluateSubExpression(
                interpreter, parseState, 0, interpreter.EngineFlags,
                interpreter.SubstitutionFlags, interpreter.EngineEventFlags,
                interpreter.ExpressionFlags, true, ref usable, ref exception,
                ref value, ref error);

            if (code == ReturnCode.Ok)
            {
                result.Value = value;
                result2 = value;
            }
            else
            {
                result.Value = error;
                result2 = error;
            }

            return code;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static StringList TestParseInteger(
            string text,
            int startIndex,
            int characters,
            byte radix,
            bool whiteSpace,
            bool greedy,
            bool unsigned
            )
        {
            int endIndex = 0;

            int intValue = Parser.ParseInteger(
                text, startIndex, characters, radix,
                whiteSpace, greedy, unsigned, ref endIndex);

            return new StringList(intValue.ToString(), endIndex.ToString());
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ResultList TestAddFunction(
            Interpreter interpreter
            )
        {
            ResultList results = new ResultList();
            long token = 0;

            ReturnCode code;
            Result result = null;

            code = interpreter.AddFunction(
                typeof(_Tests.Default), "foo", (int)Arity.None, null,
                FunctionFlags.None, null, null, true, ref token,
                ref result);

            if (code == ReturnCode.Ok)
                results.Add(code);
            else
                results.Add(result);

            code = interpreter.AddFunction(
                typeof(_Functions.Min), "bar", (int)Arity.None, null,
                FunctionFlags.None, null, null, true, ref token,
                ref result);

            if (code == ReturnCode.Ok)
                results.Add(code);
            else
                results.Add(result);

            code = interpreter.AddFunction(
                typeof(_Functions.Min), "eq", (int)Arity.None, null,
                FunctionFlags.None, null, null, true, ref token,
                ref result);

            if (code == ReturnCode.Ok)
                results.Add(code);
            else
                results.Add(result);

            code = interpreter.AddFunction(
                typeof(_Functions.Min), "eqq", (int)Arity.None, null,
                FunctionFlags.None, null, null, true, ref token,
                ref result);

            if (code == ReturnCode.Ok)
                results.Add(code);
            else
                results.Add(result);

            return results;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestAddNamedFunction(
            Interpreter interpreter,
            string name,
            IClientData clientData,
            ref Result result
            )
        {
            long token = 0;

            return interpreter.AddFunction(
                typeof(_Tests.Default.Function), name, (int)Arity.None,
                null, FunctionFlags.None, null, clientData, true,
                ref token, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestAddNamedFunction2(
            Interpreter interpreter,
            string name,
            IClientData clientData,
            ref Result result
            )
        {
            long token = 0;

            return interpreter.AddFunction(
                typeof(_Tests.Default.Function2), name, (int)Arity.Automatic,
                null, FunctionFlags.None, null, clientData, true, ref token,
                ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestAddNamedFunction3(
            Interpreter interpreter,
            string name,
            IClientData clientData,
            ref Result result
            )
        {
            long token = 0;

            return interpreter.AddFunction(
                typeof(_Tests.Default.Function3), name, (int)Arity.Automatic,
                null, FunctionFlags.None, null, clientData, true, ref token,
                ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ResultList TestRemoveFunction(
            Interpreter interpreter
            )
        {
            ResultList results = new ResultList();

            ReturnCode code;
            Result result = null;

            code = interpreter.RemoveFunction("foo", null, ref result);

            if (code == ReturnCode.Ok)
                results.Add(code);
            else
                results.Add(result);

            code = interpreter.RemoveFunction("bar", null, ref result);

            if (code == ReturnCode.Ok)
                results.Add(code);
            else
                results.Add(result);

            code = interpreter.RemoveFunction("eq", null, ref result);

            if (code == ReturnCode.Ok)
                results.Add(code);
            else
                results.Add(result);

            code = interpreter.RemoveFunction("eqq", null, ref result);

            if (code == ReturnCode.Ok)
                results.Add(code);
            else
                results.Add(result);

            return results;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestRemoveNamedFunction(
            Interpreter interpreter,
            string name,
            IClientData clientData,
            Result result
            )
        {
            return interpreter.RemoveFunction(name, clientData, ref result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestWriteBox(
            Interpreter interpreter,
            string value,
            bool multiple,
            bool newLine,
            bool restore,
            ref Result error
            )
        {
            if (interpreter != null)
            {
                IHost host = interpreter.Host;

                if (host != null)
                {
                    try
                    {
                        bool positioning = FlagOps.HasFlags(
                            host.GetFlags(), HostFlags.Positioning, true);

                        int left = 0;
                        int top = 0;

                        if (!positioning || host.GetPosition(ref left, ref top))
                        {
                            ConsoleColor foregroundColor = _ConsoleColor.None;
                            ConsoleColor backgroundColor = _ConsoleColor.None;

                            if (host.GetColors(
                                    null, "TestInfo", true, true, ref foregroundColor,
                                    ref backgroundColor, ref error) == ReturnCode.Ok)
                            {
                                if (multiple)
                                {
                                    StringList list = null;

                                    if (Parser.SplitList(
                                            interpreter, value, 0, Length.Invalid, true,
                                            ref list, ref error) == ReturnCode.Ok)
                                    {
                                        if (host.WriteBox(
                                                null, new StringPairList(list), null,
                                                newLine, restore, ref left, ref top,
                                                foregroundColor, backgroundColor))
                                        {
                                            return true;
                                        }
                                        else
                                        {
                                            error = "could not write box to interpreter host";
                                        }
                                    }
                                }
                                else
                                {
                                    if (host.WriteBox(
                                            null, value, null, newLine, restore,
                                            ref left, ref top, foregroundColor,
                                            backgroundColor))
                                    {
                                        return true;
                                    }
                                    else
                                    {
                                        error = "could not write box to interpreter host";
                                    }
                                }
                            }
                        }
                        else
                        {
                            error = "could not get interpreter host position";
                        }
                    }
                    catch (Exception e)
                    {
                        error = e;
                    }
                }
                else
                {
                    error = "interpreter host not available";
                }
            }
            else
            {
                error = "invalid interpreter";
            }

            return false;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool EnableWriteCustomInfo(
            Interpreter interpreter,
            bool enable,
            StringPairList list
            )
        {
            if (interpreter == null)
                return false;

            _Hosts.Console consoleHost = interpreter.Host as _Hosts.Console;

            if (consoleHost == null)
                return false;

            consoleHost.EnableTests(enable);

            if (enable)
            {
                if (list != null)
                    customInfoList = new StringPairList(list);
                else
                    customInfoList = new StringPairList(
                        new StringPair("Custom"), null,
                        new StringPair("name0", null),
                        new StringPair("name1", String.Empty),
                        new StringPair("name2", "value1"),
                        new StringPair("name3", TimeOps.GetUtcNow().ToString()),
                        new StringPair("name4", (interpreter.Random != null) ?
                            interpreter.Random.Next().ToString() : "0"));
            }
            else
            {
                customInfoList = null;
            }

            return true;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static bool TestWriteCustomInfo(
            Interpreter interpreter,
            bool empty,
            bool newLine,
            ConsoleColor foregroundColor,
            ConsoleColor backgroundColor
            )
        {
            if (interpreter == null)
                return false;

            _Hosts.Default defaultHost = interpreter.Host as _Hosts.Default;

            if (defaultHost == null)
                return false;

            int hostLeft = 0;
            int hostTop = 0;

            if (!defaultHost.GetDefaultPosition(ref hostLeft, ref hostTop))
                return false;

            try
            {
                OutputStyle outputStyle = defaultHost.OutputStyle;
                StringPairList list = new StringPairList(customInfoList);

                if (defaultHost.IsBoxedOutputStyle(outputStyle))
                {
                    return defaultHost.WriteBox(
                        TestCustomInfoBoxName, list, null, false, true,
                        ref hostLeft, ref hostTop, foregroundColor,
                        backgroundColor);
                }
                else if (defaultHost.IsFormattedOutputStyle(outputStyle))
                {
                    return defaultHost.WriteFormat(
                        list, newLine, foregroundColor, backgroundColor);
                }
                else if (defaultHost.IsNoneOutputStyle(outputStyle))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            finally
            {
                defaultHost.SetDefaultPosition(hostLeft, hostTop);
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Public Methods
        public void MethodWithDelegate(GetTypeCallback callback)
        {
            CheckDisposed();
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int[] TestIntArrayReturnValue()
        {
            CheckDisposed();

            return new int[] { 1, 2, 3, 4, 5 };
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string[] TestStringArrayReturnValue()
        {
            CheckDisposed();

            return new string[] { "1", "2", "joe", "jim", "tom" };
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public StringList TestStringListReturnValue()
        {
            CheckDisposed();

            return new StringList(TestStringArrayReturnValue());
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public IList<string> TestStringIListReturnValue(
            bool useCustom,
            params string[] strings
            )
        {
            CheckDisposed();

            return useCustom ?
                new StringList(strings) : new List<string>(strings);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public IList<IList<IList<string>>> TestStringIListIListIListReturnValue(
            bool useCustom,
            params string[] strings
            )
        {
            CheckDisposed();

            if (useCustom)
            {
                IList<string> list = new StringList(strings);

                IList<IList<string>> list2 = (IList<IList<string>>)
                    new GenericList<IList<string>>(list, list, list);

                IList<IList<IList<string>>> list3 = (IList<IList<IList<string>>>)
                    new GenericList<IList<IList<string>>>(list2, list2, list2);

                return list3;
            }
            else
            {
                IList<string> list = new List<string>(strings);

                IList<IList<string>> list2 = (IList<IList<string>>)
                    new List<IList<string>>(new IList<string>[] { list, list, list });

                IList<IList<IList<string>>> list3 = (IList<IList<IList<string>>>)
                    new List<IList<IList<string>>>(new IList<IList<string>>[] { list2, list2, list2 });

                return list3;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public StringList[] TestStringListArrayReturnValue()
        {
            CheckDisposed();

            return new StringList[] {
                TestStringListReturnValue(), new StringList("hello world"),
                new StringList(";"), new StringList("\\"), new StringList("{")
            };
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public IDictionary<string, string> TestStringIDictionaryReturnValue(
            bool useCustom,
            params string[] strings
            )
        {
            CheckDisposed();

            if (useCustom)
            {
                IList<string> list = new StringList(strings);

                return new GenericDictionary<string, string>(list);
            }
            else
            {
                IList<string> list = new List<string>(strings);

                return new Dictionary<string, string>(
                    new GenericDictionary<string, string>(list));
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public void TestByRefByteArray(
            int size,
            ref byte[] byteArray
            )
        {
            CheckDisposed();

            byteArray = new byte[size];

            for (int index = 0; index < size; index++)
                byteArray[index] = (byte)(index & byte.MaxValue);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode TestTwoByteArrays(
            Interpreter interpreter,
            bool randomize,
            byte[] inByteArray,
            ref byte[] outByteArray,
            ref Result error
            )
        {
            CheckDisposed();

            if (interpreter == null)
            {
                error = "invalid interpreter";
                return ReturnCode.Error;
            }

            if (inByteArray == null)
            {
                error = "invalid input byte array";
                return ReturnCode.Error;
            }

            if (randomize)
            {
                byte[] randomByteArray = new byte[inByteArray.Length];
                Random random = interpreter.Random;

                if (random != null)
                    random.NextBytes(randomByteArray);

                outByteArray = new byte[inByteArray.Length];

                for (int index = 0; index < outByteArray.Length; index++)
                {
                    outByteArray[index] = ConversionOps.ToByte(
                        inByteArray[index] ^ randomByteArray[index]);
                }
            }
            else
            {
                outByteArray = new byte[inByteArray.Length];

                for (int index = 0; index < outByteArray.Length; index++)
                    outByteArray[index] = inByteArray[index];
            }

            return ReturnCode.Ok;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public byte[] TestReturnByteArray(
            byte[] array
            )
        {
            CheckDisposed();

            //
            // WARNING: DO NOT REMOVE.  This is used by the unit tests to
            //          convert a Tcl array into a Tcl list via the Eagle
            //          marshaller.
            //
            return array;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public void TestByRefStringListArray(
            ref StringList[] list
            )
        {
            CheckDisposed();

            list = TestStringListArrayReturnValue();
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public Default TestComplexMethod(
            sbyte w,
            int x,
            bool y,
            double z,
            ref int[] t1,
            ref int[,] t2,
            ref string[] t3,
            out string t4,
            out string[] t5
            )
        {
            CheckDisposed();

            int[][] t6 = null;

            return TestComplexMethod(
                w, x, y, z, ref t1, ref t2, ref t3, out t4, out t5, out t6);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public void TestByRefNullableValueTypeMethod(
            ref int? x
            )
        {
            CheckDisposed();

            if (x != null) x++;
            else x = 0;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public object TestNullableValueTypeMethod(
            int? x
            )
        {
            CheckDisposed();

            return x;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public void TestByRefValueTypeMethod(
            ref int x
            )
        {
            CheckDisposed();

            x++;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int TestRanges(
            bool a,
            sbyte b,
            byte c,
            char d,
            short e,
            ushort f,
            int g,
            uint h,
            long i,
            ulong j,
            decimal k,
            float l,
            double m
            )
        {
            CheckDisposed();

            return 0;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public char TestCharacterMethod(
            char x
            )
        {
            CheckDisposed();

            return x;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public void TestByRefCharacterArrayMethod(
            ref char[] x
            )
        {
            CheckDisposed();

            x = new char[] { 'f', 'o', 'o' };
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public string TestGetPrivateField()
        {
            CheckDisposed();

            return privateField;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public Default TestComplexMethod(
            sbyte w,
            int x,
            bool y,
            double z,
            ref int[] t1,
            ref int[,] t2,
            ref string[] t3,
            out string t4,
            out string[] t5,
            out int[][] t6
            )
        {
            CheckDisposed();

            if (y)
                t1[0]++;

            if (z > 1)
            {
#if !MONO_BUILD
                t2[-1, -2] += 20;
#endif

                t2[0, 0]++;
                t2[0, 1] *= 2;
                t2[1, 0]--;
                t2[1, 1] /= 2;
                t2[2, 1] += 21;
            }

            if (x > 0)
                //
                // BUGFIX: We do not want to complicate the test case to account
                //         for negative numbers here; therefore, just use the
                //         absolute value.
                //
                t3[0] = Math.Abs(Environment.TickCount).ToString();

            //
            // BUGFIX: Cannot be locale-specific here.
            //
            t4 = FormatOps.Iso8601DateTime(TimeOps.GetUtcNow(), true);

            t5 = new string[] {
                w.ToString(), x.ToString(), y.ToString(), z.ToString()
            };

            t6 = new int[][] {
                new int[] { 0, 1, 2 }, new int[] { 2, 4, 6 }, new int[] { 8, 16, 32 }
            };

            return new Default(w);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if !MONO_BUILD
        public int[,] TestMoreComplexMethod(
            bool y,
            ref int[,] t7
            )
        {
            if (y)
            {
                t7 = (int[,])Array.CreateInstance(
                    typeof(int), new int[] { 4, 5 }, new int[] { -6, 6 });
            }
            else
            {
                t7[-6, 6] += -6 * 6;
                t7[-6, 7] += -6 * 7;
                t7[-6, 8] += -6 * 8;
                t7[-6, 9] += -6 * 9;
                t7[-6, 10] += -6 * 10;

                t7[-5, 6] += -5 * 6;
                t7[-5, 7] += -5 * 7;
                t7[-5, 8] += -5 * 8;
                t7[-5, 9] += -5 * 9;
                t7[-5, 10] += -5 * 10;

                t7[-4, 6] += -4 * 6;
                t7[-4, 7] += -4 * 7;
                t7[-4, 8] += -4 * 8;
                t7[-4, 9] += -4 * 9;
                t7[-4, 10] += -4 * 10;

                t7[-3, 6] += -3 * 6;
                t7[-3, 7] += -3 * 7;
                t7[-3, 8] += -3 * 8;
                t7[-3, 9] += -3 * 9;
                t7[-3, 10] += -3 * 10;
            }

            return t7;
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode TestSetVariableLinks(
            Interpreter interpreter,
            string stringName,
            string objectName,
            string integerName,
            string propertyName,
            bool useString,
            bool useObject,
            bool useInteger,
            bool useProperty,
            bool quiet,
            ref Result error
            )
        {
            CheckDisposed();

            if (interpreter != null)
            {
                ResultList errors = null;

                if (useString)
                {
                    FieldInfo fieldInfo = null;

                    try
                    {
                        fieldInfo = GetType().GetField("privateField",
                            MarshalOps.PrivateInstanceGetFieldBindingFlags);
                    }
                    catch (Exception e)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(e);

                        if (!quiet)
                            DebugOps.Complain(interpreter, ReturnCode.Error, e);
                    }

                    if (fieldInfo != null)
                    {
                        ReturnCode setCode;
                        Result setError = null;

                        setCode = interpreter.SetVariableLink(
                            VariableFlags.None, stringName, fieldInfo,
                            this, ref setError);

                        if (setCode != ReturnCode.Ok)
                        {
                            if (errors == null)
                                errors = new ResultList();

                            errors.Add(setError);

                            if (!quiet)
                                DebugOps.Complain(interpreter, setCode, setError);
                        }
                    }
                }

                if (useObject)
                {
                    FieldInfo fieldInfo = null;

                    try
                    {
                        fieldInfo = GetType().GetField("objectField",
                            MarshalOps.PrivateInstanceGetFieldBindingFlags);
                    }
                    catch (Exception e)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(e);

                        if (!quiet)
                            DebugOps.Complain(interpreter, ReturnCode.Error, e);
                    }

                    if (fieldInfo != null)
                    {
                        ReturnCode setCode;
                        Result setError = null;

                        setCode = interpreter.SetVariableLink(
                            VariableFlags.None, objectName, fieldInfo,
                            this, ref setError);

                        if (setCode != ReturnCode.Ok)
                        {
                            if (errors == null)
                                errors = new ResultList();

                            errors.Add(setError);

                            if (!quiet)
                                DebugOps.Complain(interpreter, setCode, setError);
                        }
                    }
                }

                if (useInteger)
                {
                    FieldInfo fieldInfo = null;

                    try
                    {
                        fieldInfo = GetType().GetField("intField",
                            MarshalOps.PublicInstanceGetFieldBindingFlags);
                    }
                    catch (Exception e)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(e);

                        if (!quiet)
                            DebugOps.Complain(interpreter, ReturnCode.Error, e);
                    }

                    if (fieldInfo != null)
                    {
                        ReturnCode setCode;
                        Result setError = null;

                        setCode = interpreter.SetVariableLink(
                            VariableFlags.None, integerName, fieldInfo,
                            this, ref setError);

                        if (setCode != ReturnCode.Ok)
                        {
                            if (errors == null)
                                errors = new ResultList();

                            errors.Add(setError);

                            if (!quiet)
                                DebugOps.Complain(interpreter, setCode, setError);
                        }
                    }
                }

                if (useProperty)
                {
                    PropertyInfo propertyInfo = null;

                    try
                    {
                        propertyInfo = GetType().GetProperty("SimpleIntProperty",
                            MarshalOps.PublicInstanceGetPropertyBindingFlags);
                    }
                    catch (Exception e)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(e);

                        if (!quiet)
                            DebugOps.Complain(interpreter, ReturnCode.Error, e);
                    }

                    if (propertyInfo != null)
                    {
                        ReturnCode setCode;
                        Result setError = null;

                        setCode = interpreter.SetVariableLink(
                            VariableFlags.None, propertyName, propertyInfo,
                            this, ref setError);

                        if (setCode != ReturnCode.Ok)
                        {
                            if (errors == null)
                                errors = new ResultList();

                            errors.Add(setError);

                            if (!quiet)
                                DebugOps.Complain(interpreter, setCode, setError);
                        }
                    }
                }

                if (errors == null)
                    return ReturnCode.Ok;

                error = errors;
            }
            else
            {
                error = "invalid interpreter";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode TestUnsetVariableLinks(
            Interpreter interpreter,
            string stringName,
            string objectName,
            string integerName,
            string propertyName,
            bool useString,
            bool useObject,
            bool useInteger,
            bool useProperty,
            bool quiet,
            ref Result error
            )
        {
            CheckDisposed();

            if (interpreter != null)
            {
                ResultList errors = null;

                if (useString)
                {
                    ReturnCode unsetCode;
                    Result unsetError = null;

                    unsetCode = interpreter.UnsetVariable(
                        VariableFlags.None, stringName, ref unsetError);

                    if (unsetCode != ReturnCode.Ok)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(unsetError);

                        if (!quiet)
                            DebugOps.Complain(interpreter, unsetCode, unsetError);
                    }
                }

                if (useObject)
                {
                    ReturnCode unsetCode;
                    Result unsetError = null;

                    unsetCode = interpreter.UnsetVariable(
                        VariableFlags.None, objectName, ref unsetError);

                    if (unsetCode != ReturnCode.Ok)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(unsetError);

                        if (!quiet)
                            DebugOps.Complain(interpreter, unsetCode, unsetError);
                    }
                }

                if (useInteger)
                {
                    ReturnCode unsetCode;
                    Result unsetError = null;

                    unsetCode = interpreter.UnsetVariable(
                        VariableFlags.None, integerName, ref unsetError);

                    if (unsetCode != ReturnCode.Ok)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(unsetError);

                        if (!quiet)
                            DebugOps.Complain(interpreter, unsetCode, unsetError);
                    }
                }

                if (useProperty)
                {
                    ReturnCode unsetCode;
                    Result unsetError = null;

                    unsetCode = interpreter.UnsetVariable(
                        VariableFlags.None, propertyName, ref unsetError);

                    if (unsetCode != ReturnCode.Ok)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(unsetError);

                        if (!quiet)
                            DebugOps.Complain(interpreter, unsetCode, unsetError);
                    }
                }

                if (errors == null)
                    return ReturnCode.Ok;

                error = errors;
            }
            else
            {
                error = "invalid interpreter";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode TestSetVariableSystemArray(
            Interpreter interpreter,
            string intPtrName,
            string objectName,
            bool useIntPtr,
            bool useObject,
            bool quiet,
            ref Result error
            )
        {
            CheckDisposed();

            if (interpreter != null)
            {
                ResultList errors = null;

                if (useIntPtr)
                {
                    ReturnCode setCode;
                    Result setError = null;

                    setCode = interpreter.SetVariableSystemArray(
                        VariableFlags.None, intPtrName, intPtrArrayField,
                        ref error);

                    if (setCode != ReturnCode.Ok)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(setError);

                        if (!quiet)
                            DebugOps.Complain(interpreter, setCode, setError);
                    }
                }

                if (useObject)
                {
                    ReturnCode setCode;
                    Result setError = null;

                    setCode = interpreter.SetVariableSystemArray(
                        VariableFlags.None, objectName, objectArrayField,
                        ref error);

                    if (setCode != ReturnCode.Ok)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(setError);

                        if (!quiet)
                            DebugOps.Complain(interpreter, setCode, setError);
                    }
                }

                if (errors == null)
                    return ReturnCode.Ok;

                error = errors;
            }
            else
            {
                error = "invalid interpreter";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode TestUnsetVariableSystemArray(
            Interpreter interpreter,
            string intPtrName,
            string objectName,
            bool useIntPtr,
            bool useObject,
            bool quiet,
            ref Result error
            )
        {
            CheckDisposed();

            if (interpreter != null)
            {
                ResultList errors = null;

                if (useIntPtr)
                {
                    ReturnCode unsetCode;
                    Result unsetError = null;

                    unsetCode = interpreter.UnsetVariable(
                        VariableFlags.None, intPtrName, ref unsetError);

                    if (unsetCode != ReturnCode.Ok)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(unsetError);

                        if (!quiet)
                            DebugOps.Complain(interpreter, unsetCode, unsetError);
                    }
                }

                if (useObject)
                {
                    ReturnCode unsetCode;
                    Result unsetError = null;

                    unsetCode = interpreter.UnsetVariable(
                        VariableFlags.None, objectName, ref unsetError);

                    if (unsetCode != ReturnCode.Ok)
                    {
                        if (errors == null)
                            errors = new ResultList();

                        errors.Add(unsetError);

                        if (!quiet)
                            DebugOps.Complain(interpreter, unsetCode, unsetError);
                    }
                }

                if (errors == null)
                    return ReturnCode.Ok;

                error = errors;
            }
            else
            {
                error = "invalid interpreter";
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public void TestEvaluateAsyncCallback(IAsynchronousContext context)
        {
            CheckDisposed();

            if (context != null)
                //
                // NOTE: Capture async result.
                //
                asyncResult = ResultOps.Format(
                    context.ReturnCode, context.Result, context.ErrorLine);

            if (@event != null)
                ThreadOps.SetEvent(@event);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public ReturnCode TestEvaluateAsync(
            Interpreter interpreter,
            string text,
            EngineFlags engineFlags,
            SubstitutionFlags substitutionFlags,
            EventFlags eventFlags,
            ExpressionFlags expressionFlags,
            int timeout,
            ref Result result
            )
        {
            CheckDisposed();

            if (interpreter != null)
            {
                if (Engine.EvaluateScript(
                        interpreter, text, engineFlags, substitutionFlags,
                        eventFlags, expressionFlags, TestEvaluateAsyncCallback,
                        null, ref result) == ReturnCode.Ok)
                {
                    if (@event != null)
                    {
                        if (timeout == _Timeout.Infinite)
                            timeout = interpreter.Timeout;

                        if (ThreadOps.WaitEvent(@event, timeout))
                        {
                            //
                            // NOTE: Return async result.
                            //
                            result = asyncResult;

                            return ReturnCode.Ok;
                        }
                        else
                        {
                            result = String.Format(
                                "waited {0} milliseconds for script to complete",
                                timeout);
                        }

                        //
                        // NOTE: Reset event for next time.
                        //
                        ThreadOps.ResetEvent(@event);
                    }
                    else
                    {
                        //
                        // NOTE: No event is setup, skip waiting.
                        //
                        return ReturnCode.Ok;
                    }
                }
            }
            else
            {
                result = "invalid interpreter";
            }

            return ReturnCode.Error;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Private Static Methods
        #region Methods for Ad-Hoc Commands
        private static void TestVoidMethod(
            string value
            )
        {
            //
            // NOTE: Write a string to the console as long as it is not null.
            //
            if (value == null)
                throw new ArgumentNullException();

            Interpreter interpreter = Interpreter.GetActive();

            if (interpreter == null)
                throw new ScriptException("invalid interpreter");

            ReturnCode code;
            Result result = null;

            code = ScriptOps.WriteViaIExecute(
                interpreter, null, null, value, ref result);

            if (code != ReturnCode.Ok)
                throw new ScriptException(code, result);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static long TestLongMethod(
            DateTime dateTime
            )
        {
            //
            // NOTE: Just return the number of ticks.
            //
            return dateTime.Ticks;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static IEnumerable TestIEnumerableMethod(
            ICommand command
            )
        {
            //
            // NOTE: Return the sub-commands for the command.
            //
            if (command != null)
            {
                EnsembleDictionary subCommands = command.SubCommands;

                if (subCommands != null)
                {
                    StringList result = new StringList(subCommands.Keys);
                    result.Sort(); return result;
                }
            }

            return null;
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static ReturnCode TestShellArgumentCallback(
            Interpreter interpreter,
            IInteractiveHost interactiveHost,
            IClientData clientData,
            int count,
            string arg,
            ref IList<string> argv,
            ref Result result
            )
        {
            int argc = (argv != null) ? argv.Count : 0;

            if ((count > 0) &&
                StringOps.MatchSwitch(arg, "one"))
            {
                GenericOps<string>.PopFirstArgument(ref argv);

                result += String.Format(
                    "argument one OK{0}",
                    Characters.Pipe);

                return ReturnCode.Ok;
            }
            else if ((count > 0) &&
                StringOps.MatchSwitch(arg, "two"))
            {
                if (argc >= 2)
                {
                    string value = argv[1];

                    GenericOps<string>.PopFirstArgument(ref argv);
                    GenericOps<string>.PopFirstArgument(ref argv);

                    result += String.Format(
                        "argument two \"{0}\" OK{1}",
                        value, Characters.Pipe);

                    return ReturnCode.Ok;
                }
                else
                {
                    result += String.Format(
                        "wrong # args: should be \"-two <value>\"{0}",
                        Characters.Pipe);
                }
            }
            else if ((count > 0) &&
                StringOps.MatchSwitch(arg, "three"))
            {
                GenericOps<string>.PopFirstArgument(ref argv);

                result += String.Format(
                    "argument three ERROR{0}",
                    Characters.Pipe);
            }
            else
            {
                result += String.Format(
                    "invalid test argument \"{0}\"{1}",
                    arg, Characters.Pipe);
            }

            return ReturnCode.Error;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static DateTime TestDateTimeNow()
        {
            if (nowIncrement != 0)
                now = now.AddTicks(nowIncrement);

            return now;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static TypeList GetParameterTypeList(
            MethodInfo methodInfo
            )
        {
            TypeList result = new TypeList();

            if (methodInfo != null)
                foreach (ParameterInfo parameterInfo in methodInfo.GetParameters())
                    result.Add(parameterInfo.ParameterType);

            return result;
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NATIVE && TCL
        private static IntPtrList TestIntPtrList()
        {
            return new IntPtrList(new IntPtr[] {
                new IntPtr(-1), IntPtr.Zero, new IntPtr(1)
            });
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        private static CharList TestCharList()
        {
            return new CharList(Characters.ReservedCharList);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Public Static Properties
        public static Type StaticTypeProperty
        {
            get { return staticTypeField; }
            set { staticTypeField = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static object StaticObjectProperty
        {
            get { return staticObjectField; }
            set { staticObjectField = value; }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Public Properties
        public Type TypeProperty
        {
            get { CheckDisposed(); return typeField; }
            set { CheckDisposed(); typeField = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public object ObjectProperty
        {
            get { CheckDisposed(); return objectField; }
            set { CheckDisposed(); objectField = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public bool SimpleBoolProperty
        {
            get { CheckDisposed(); return boolField; }
            set { CheckDisposed(); boolField = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public byte SimpleByteProperty
        {
            get { CheckDisposed(); return byteField; }
            set { CheckDisposed(); byteField = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public short SimpleShortProperty
        {
            get { CheckDisposed(); return shortField; }
            set { CheckDisposed(); shortField = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int SimpleIntProperty
        {
            get { CheckDisposed(); return intField; }
            set { CheckDisposed(); intField = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public long SimpleLongProperty
        {
            get { CheckDisposed(); return longField; }
            set { CheckDisposed(); longField = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public decimal SimpleDecimalProperty
        {
            get { CheckDisposed(); return decimalField; }
            set { CheckDisposed(); decimalField = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int ReadOnlyProperty
        {
            get { CheckDisposed(); return intField; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Indexer Properties
        public int this[int index]
        {
            get { CheckDisposed(); return intArrayField[index]; }
            set { CheckDisposed(); intArrayField[index] = value; }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public int this[int index, string more]
        {
            get { CheckDisposed(); return intArrayField[index]; }
            set { CheckDisposed(); intArrayField[index] = value; }
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IDisposable Test Class
        [ObjectId("4b0d4629-b42f-4cfa-adb6-5943e098961c")]
        public sealed class Disposable : IDisposable
        {
            #region Public Constructors
            public Disposable()
            {
                id = GlobalState.NextId();
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Public Properties
            private long id;
            public long Id
            {
                get { CheckDisposed(); return id; }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            private string name;
            public string Name
            {
                get { CheckDisposed(); return name; }
                set { CheckDisposed(); name = value; }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public bool Disposed
            {
                //
                // NOTE: *WARNING* Do not uncomment the CheckDisposed call here
                //       as that would defeat the purpose of this method and
                //       may interfere with the associated test cases.
                //
                get { /* CheckDisposed(); */ return disposed; }
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public bool Disposing
            {
                //
                // NOTE: *WARNING* Do not uncomment the CheckDisposed call here
                //       as that would defeat the purpose of this method and
                //       may interfere with the associated test cases.
                //
                get { /* CheckDisposed(); */ return disposing; }
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region System.Object Overrides
            public override string ToString()
            {
                //
                // NOTE: *WARNING* Do not uncomment the CheckDisposed call here
                //       as that would defeat the purpose of this method and
                //       may interfere with the associated test cases.
                //
                // CheckDisposed();

                return String.Format(
                    "id = {0}, disposing = {1}, disposed = {2}",
                    id, disposing, disposed);
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region IDisposable "Pattern" Members
            private bool disposed;
            private void CheckDisposed() /* throw */
            {
#if THROW_ON_DISPOSED
                if (disposed && Engine.IsThrowOnDisposed(null, false))
                    throw new ObjectDisposedException(typeof(Disposable).Name);
#endif
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            private bool disposing;
            private /* protected virtual */ void Dispose(
                bool disposing
                )
            {
                if (!disposed)
                {
                    //
                    // NOTE: Keep track of whether we were disposed via the
                    //       destructor (i.e. most likely via the GC) or
                    //       explicitly via the public Dispose method.
                    //
                    this.disposing = disposing;

                    //
                    // NOTE: This object is now disposed.  The test cases may
                    //       query the property associated with this field to
                    //       discover this fact.
                    //
                    disposed = true;
                }
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region IDisposable Members
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Destructor
            ~Disposable()
            {
                Dispose(false);
            }
            #endregion
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IFunction Test Classes
        #region IFunction Test Class #1
        [ObjectId("a61370f5-215a-41a3-af8f-196fcf8f3cc4")]
        [FunctionFlags(FunctionFlags.Safe)]
        [Arguments(Arity.Unary)]
        [ObjectGroup("test")]
        public sealed class Function : _Functions.Default
        {
            #region Public Constructors
            public Function(
                IFunctionData functionData
                )
                : base(functionData)
            {
                this.Flags |= AttributeOps.GetFunctionFlags(GetType().BaseType) |
                    AttributeOps.GetFunctionFlags(this);
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region IExecuteArgument Members
            public override ReturnCode Execute(
                Interpreter interpreter,
                IClientData clientData,
                ArgumentList arguments,
                ref Argument value,
                ref Result error
                )
            {
                ReturnCode code;

                if (arguments.Count == 2)
                {
                    string text = arguments[1];
                    Result result = null;

                    code = Engine.EvaluateExpression(
                        interpreter, text, ref result);

                    if (code == ReturnCode.Ok)
                        value = StringList.MakeList(text, result);
                    else
                        error = result;
                }
                else
                {
                    error = ScriptOps.WrongNumberOfArguments(
                        this, 1, arguments, "expr");

                    code = ReturnCode.Error;
                }

                return code;
            }
            #endregion
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IFunction Test Class #2
        [ObjectId("f7051cc9-57b1-4307-b4b6-1216811b9d39")]
        [FunctionFlags(FunctionFlags.Unsafe)]
        [Arguments(Arity.Binary)]
        [ObjectGroup("test")]
        public sealed class Function2 : _Functions.Default
        {
            #region Public Constructors
            public Function2(
                IFunctionData functionData
                )
                : base(functionData)
            {
                this.Flags |= AttributeOps.GetFunctionFlags(GetType().BaseType) |
                    AttributeOps.GetFunctionFlags(this);
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region IExecuteArgument Members
            public override ReturnCode Execute(
                Interpreter interpreter,
                IClientData clientData,
                ArgumentList arguments,
                ref Argument value,
                ref Result error
                )
            {
                ReturnCode code = ReturnCode.Ok;

                if (arguments.Count == (this.Arguments + 1)) /* 3 */
                {
                    bool boolValue = false;

                    if (Engine.ToBoolean(
                            arguments[1], interpreter.CultureInfo,
                            ref boolValue, ref error) != ReturnCode.Ok)
                    {
                        return ReturnCode.Error;
                    }

                    if (boolValue)
                    {
                        try
                        {
                            //
                            // NOTE: This is being purely for expression engine
                            //       testing purposes only.  Normally, the
                            //       interpreter should NOT be disposed from
                            //       inside of a custom command or function.
                            //
                            if (interpreter != null)
                            {
                                interpreter.Dispose();
                                interpreter = null;
                            }

                            code = ReturnCode.Ok;
                        }
                        catch (Exception e)
                        {
                            error = e;
                            code = ReturnCode.Error;
                        }
                    }

                    string text = arguments[2];

                    if ((code == ReturnCode.Ok) && !String.IsNullOrEmpty(text))
                    {
                        Result result = null;

                        code = Engine.EvaluateExpression(
                            interpreter, text, ref result);

                        if (code == ReturnCode.Ok)
                            value = StringList.MakeList(text, result);
                        else
                            error = result;
                    }
                }
                else
                {
                    error = ScriptOps.WrongNumberOfArguments(
                        this, 1, arguments, "bool expr");

                    code = ReturnCode.Error;
                }

                return code;
            }
            #endregion
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IFunction Test Class #3
        [ObjectId("c06da159-fe1f-4482-85ec-1b4c3bf4d0d0")]
        [FunctionFlags(FunctionFlags.Unsafe)]
        [Arguments(Arity.None)]
        [ObjectGroup("test")]
        public sealed class Function3 : _Functions.Default
        {
            #region Public Constructors
            public Function3(
                IFunctionData functionData
                )
                : base(functionData)
            {
                this.Flags |= AttributeOps.GetFunctionFlags(GetType().BaseType) |
                    AttributeOps.GetFunctionFlags(this);
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region IExecuteArgument Members
            public override ReturnCode Execute(
                Interpreter interpreter,
                IClientData clientData,
                ArgumentList arguments,
                ref Argument value,
                ref Result error
                )
            {
                if (interpreter == null)
                {
                    error = "invalid interpreter";
                    return ReturnCode.Error;
                }

                if (arguments == null)
                {
                    error = "invalid argument list";
                    return ReturnCode.Error;
                }

                if (arguments.Count < 3)
                {
                    error = ScriptOps.WrongNumberOfArguments(
                        this, 1, arguments, "bool arg ?arg ...?");

                    return ReturnCode.Error;
                }

                bool boolValue = false;

                if (Engine.ToBoolean(
                        arguments[1], interpreter.CultureInfo,
                        ref boolValue, ref error) != ReturnCode.Ok)
                {
                    return ReturnCode.Error;
                }

                ReturnCode code;

                if (boolValue)
                {
                    Result result = null;

                    code = interpreter.Invoke(arguments[2], clientData,
                        ArgumentList.GetRange(arguments, 2), ref result);

                    if (code == ReturnCode.Ok)
                        value = result;
                    else
                        error = result;
                }
                else
                {
                    value = ArgumentList.GetRange(
                        arguments, 1, Index.Invalid, false).ToString();

                    code = ReturnCode.Ok;
                }

                return code;
            }
            #endregion
        }
        #endregion
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Generic List Class
#if SERIALIZATION
        [Serializable()]
#endif
        [ObjectId("df724c7b-bf7a-4292-8223-c2350b6f3dc2")]
        public sealed class GenericList<T> : List<T>
        {
            #region Public Constructors
            public GenericList()
                : base()
            {
                // do nothing.
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public GenericList(
                IEnumerable<T> collection
                )
                : base(collection)
            {
                // do nothing.
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public GenericList(
                params T[] elements
                )
                : base(elements)
            {
                // do nothing.
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region ToString Methods
            public string ToString(
                string pattern,
                bool noCase
                )
            {
                return GenericOps<T>.ListToString(
                    this, Index.Invalid, Index.Invalid, ToStringFlags.None,
                    Characters.Space.ToString(), pattern, noCase);
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region System.Object Overrides
            public override string ToString()
            {
                return ToString(null, false);
            }
            #endregion
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Generic Dictionary Class
#if SERIALIZATION
        [Serializable()]
#endif
        [ObjectId("51e22e50-4079-48f6-83eb-e48cb49c7ea3")]
        public sealed class GenericDictionary<TKey, TValue> : Dictionary<TKey, TValue>
        {
            #region Public Constructors
            public GenericDictionary()
                : base()
            {
                // do nothing.
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public GenericDictionary(
                IEnumerable<TKey> collection
                )
                : this(collection, null)
            {
                // do nothing.
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public GenericDictionary(
                params TKey[] elements
                )
                : this((IEnumerable<TKey>)elements)
            {
                // do nothing.
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public GenericDictionary(
                IEnumerable<TKey> keys,
                IEnumerable<TValue> values
                )
                : this()
            {
                Add(keys, values);
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Protected Constructors
#if SERIALIZATION
            private GenericDictionary(
                SerializationInfo info,
                StreamingContext context
                )
                : base(info, context)
            {
                // do nothing.
            }
#endif
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region Add Methods
            public void Add(
                IEnumerable<TKey> keys,
                IEnumerable<TValue> values
                )
            {
                if (keys == null)
                    return;

                IEnumerator<TKey> keyEnumerator = keys.GetEnumerator();

                IEnumerator<TValue> valueEnumerator = (values != null) ?
                    values.GetEnumerator() : null;

                bool moreValues = (valueEnumerator != null);

                while (keyEnumerator.MoveNext())
                {
                    TKey key = keyEnumerator.Current;
                    TValue value = default(TValue);

                    if (moreValues)
                    {
                        if (valueEnumerator.MoveNext())
                            value = valueEnumerator.Current;
                        else
                            moreValues = false;
                    }

                    this.Add(key, value);
                }
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region ToString Methods
            public string ToString(
                string pattern,
                bool noCase
                )
            {
                return GenericOps<TKey, TValue>.ListToString(
                    this, Index.Invalid, Index.Invalid, ToStringFlags.None,
                    Characters.Space.ToString(), pattern, noCase);
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region System.Object Overrides
            public override string ToString()
            {
                return ToString(null, false);
            }
            #endregion
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Derived List Class
#if SERIALIZATION
        [Serializable()]
#endif
        [ObjectId("99cda455-3f92-4ec7-bf6e-a406c76ddbf5")]
        public sealed class DerivedList : List<DerivedList>
        {
            #region Public Constructors
            public DerivedList()
                : base()
            {
                // do nothing.
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public DerivedList(
                IEnumerable<DerivedList> collection
                )
                : base(collection)
            {
                // do nothing.
            }

            ///////////////////////////////////////////////////////////////////////////////////////////

            public DerivedList(
                params DerivedList[] elements
                )
                : base(elements)
            {
                // do nothing.
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region ToString Methods
            public string ToString(
                string pattern,
                bool noCase
                )
            {
                return GenericOps<DerivedList>.ListToString(
                    this, Index.Invalid, Index.Invalid, ToStringFlags.None,
                    Characters.Space.ToString(), pattern, noCase);
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////

            #region System.Object Overrides
            public override string ToString()
            {
                return ToString(null, false);
            }
            #endregion
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Remote Authorizer Class (Conditional)
#if NETWORK && REMOTING
        [ObjectId("008a9889-79c4-4a75-af68-1bbb56a349b3")]
        public sealed class RemoteAuthorizer : IAuthorizeRemotingConnection
        {
            #region IAuthorizeRemotingConnection Members
            public bool IsConnectingEndPointAuthorized(EndPoint endPoint)
            {
                IPEndPoint ipEndPoint = endPoint as IPEndPoint;

                if ((ipEndPoint != null) &&
                    (ipEndPoint.Address != null) &&
                    (ipEndPoint.Address.Equals(IPAddress.Loopback)))
                {
                    return true;
                }

                return false;
            }
            ///////////////////////////////////////////////////////////////////////////////////////////////

            public bool IsConnectingIdentityAuthorized(
                IIdentity identity
                )
            {
                return true;
            }
            #endregion
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Remote Object Class
        [ObjectId("2d6c5daa-884a-4ee5-a654-20b70cee463f")]
        public sealed class RemoteObject : MarshalByRefObject, IDisposable
        {
            #region Public Methods (Remotely Accessible)
            public DateTime Now()
            {
                CheckDisposed();

                return TimeOps.GetUtcNow();
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////

            public bool Exit()
            {
                CheckDisposed();

#if REMOTING
                try
                {
                    TcpServerChannel channel =
                        (TcpServerChannel)ChannelServices.GetChannel(String.Empty);

                    if (channel != null)
                    {
                        if (RemotingServices.Disconnect(this))
                        {
                            channel.StopListening(null);
                            ChannelServices.UnregisterChannel(channel);

                            return true;
                        }
                    }
                }
                catch
                {
                    // do nothing.
                }
#endif

                return false;
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////

            public ReturnCode Evaluate(
                string text,
                EngineFlags engineFlags,
                SubstitutionFlags substitutionFlags,
                EventFlags eventFlags,
                ExpressionFlags expressionFlags,
                ref Result result
                )
            {
                CheckDisposed();

                return Engine.EvaluateScript(
                    Interpreter.GetAny(), text,
                    engineFlags, substitutionFlags,
                    eventFlags, expressionFlags,
                    ref result);
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////////

            #region IDisposable Members
            //
            // HACK: We can never unset the variable that contains the transparent
            //       proxy reference unless this class implements IDisposable because
            //       the transparent proxy "pretends" to implement it, thereby fooling
            //       our TryDisposeObject function.
            //
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////////

            #region IDisposable "Pattern" Members
            private bool disposed;
            private void CheckDisposed() /* throw */
            {
#if THROW_ON_DISPOSED
                if (disposed && Engine.IsThrowOnDisposed(null, false))
                    throw new ObjectDisposedException(typeof(RemoteObject).Name);
#endif
            }

            ///////////////////////////////////////////////////////////////////////////////////////////////

            private /* protected virtual */ void Dispose(bool disposing)
            {
                if (!disposed)
                {
                    //if (disposing)
                    //{
                    //    ////////////////////////////////////
                    //    // dispose managed resources here...
                    //    ////////////////////////////////////
                    //}

                    //////////////////////////////////////
                    // release unmanaged resources here...
                    //////////////////////////////////////

                    disposed = true;
                }
            }
            #endregion

            ///////////////////////////////////////////////////////////////////////////////////////////////

            #region Destructor
            ~RemoteObject()
            {
                Dispose(false);
            }
            #endregion
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Conditional Public Static Methods
#if XML
        public static void TestScriptStreamXml(
            Interpreter interpreter
            )
        {
            string value = String.Format(
                "<?xml version=\"1.0\" encoding=\"utf-8\" ?>{0}" +
                "<blocks xmlns=\"https://eagle.to/2009/schema\">" +
                "  <block id=\"11b0bd2a-bc99-4639-9727-dc38efacaca1\" type=\"automatic\" name=\"block1\">{0}" +
                "    <![CDATA[{0}" +
                "      set seconds [clock seconds]{0}" +
                "      lappend seconds \"clock time = $seconds\"{0}" +
                "      lappend seconds [expr {1}$seconds > 0 ? $seconds : \"negative\"{2}]{0}" +
                "    ]]>{0}" +
                "  </block>{0}" +
                "  <block id=\"07a3570a-49ab-45d7-9e1a-893b2c61edff\" type=\"automatic\" name=\"block2\">{0}" +
                "    return [list {1}this is a test.{2} $seconds [clock seconds]]{0}" +
                "  </block>{0}" +
                "</blocks>{0}" + Characters.EndOfFile + "this is not valid XML",
                Environment.NewLine, Characters.OpenBrace, Characters.CloseBrace);

            ReturnCode code;
            Result result = null;
            string extra = null;

            using (StringReader stringReader = new StringReader(value))
            {
                string text = null;

                code = Engine.ReadScriptStream(
                    interpreter, null, stringReader, 0,
                    Count.Invalid, ref text, ref result);

                if (code == ReturnCode.Ok)
                    result = text;

                extra = stringReader.ReadToEnd();
            }

            IInteractiveHost interactiveHost = interpreter.Host;

            if (interactiveHost != null)
            {
                interactiveHost.WriteResultLine(code, result);
                interactiveHost.WriteResultLine(code, extra);

                code = Engine.EvaluateScript(interpreter, result, ref result);

                interactiveHost.WriteResultLine(code, result);
            }
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        //
        // HACK: This will *NOT* build using Mono/XBuild.  Additionally,
        //       this method will not execute correctly on Mono due to a
        //       missing constructor for TcpServerChannel and incomplete
        //       support for .NET Remoting in general.
        //
#if !MONO && !MONO_BUILD && NETWORK && REMOTING
        public static ReturnCode TestRemoting(
            Interpreter interpreter,
            int port,
            string uri,
            WellKnownObjectMode mode,
            ref Result error
            )
        {
            try
            {
                IDictionary sinkProperties = new Hashtable();

                //
                // NOTE: Allow all types to be used.
                //
                sinkProperties.Add("typeFilterLevel", "Full");

                BinaryServerFormatterSinkProvider sinkProvider =
                    new BinaryServerFormatterSinkProvider(
                        sinkProperties, null);

                IDictionary channelProperties = new Hashtable();

                channelProperties.Add("name", String.Empty);
                channelProperties.Add("port", port);

                //
                // NOTE: Value of "true" causes client hang when
                //       no config is used to setup the channel.
                //
                channelProperties.Add("secure", false);

                TcpServerChannel channel = new TcpServerChannel(
                    channelProperties, sinkProvider, new RemoteAuthorizer());

                ChannelServices.RegisterChannel(channel, false);

                RemotingConfiguration.RegisterWellKnownServiceType(
                    typeof(RemoteObject), uri, mode);

                return ReturnCode.Ok;
            }
            catch (Exception e)
            {
                error = e;
            }

            return ReturnCode.Error;
        }
#endif

        ///////////////////////////////////////////////////////////////////////////////////////////////

        public static ReturnCode TestManagedDelegate(
            Interpreter interpreter,
            ref Type type,
            ref Result error
            )
        {
            return DelegateOps.CreateManagedDelegateType(
                interpreter, null, null, null, null, typeof(void),
                new TypeList(new Type[] { typeof(string) }), ref type,
                ref error);
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

#if NATIVE && LIBRARY
        private static ReturnCode TestNativeDelegate(
            Interpreter interpreter,
            ref IDelegate @delegate,
            ref Result error
            )
        {
            return DelegateOps.CreateNativeDelegateType(
                interpreter, null, null, null, null, CallingConvention.Cdecl,
                true, (CharSet)0, false, false, typeof(ReturnCode),
                new TypeList(new Type[] {
                    typeof(int), typeof(IntPtr).MakeByRefType(),
                    typeof(Result).MakeByRefType(), typeof(bool)
                }), null, null, null, IntPtr.Zero, ref @delegate, ref error);
        }
#endif
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IDisposable Members
        public void Dispose()
        {
            #region Dead Code
#if DEAD_CODE
            if (intField == 999)
                throw new ScriptException(ReturnCode.Error, "dispose failure test");
#endif
            #endregion

            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region IDisposable "Pattern" Members
        private bool disposed;
        private void CheckDisposed() /* throw */
        {
#if THROW_ON_DISPOSED
            if (disposed && Engine.IsThrowOnDisposed(null, false))
                throw new ObjectDisposedException(typeof(Default).Name);
#endif
        }

        ///////////////////////////////////////////////////////////////////////////////////////////////

        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    ////////////////////////////////////
                    // dispose managed resources here...
                    ////////////////////////////////////

                    ThreadOps.CloseEvent(ref @event);
                }

                //////////////////////////////////////
                // release unmanaged resources here...
                //////////////////////////////////////

                disposed = true;
            }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////////////////////////////

        #region Destructor
        ~Default()
        {
            Dispose(false);
        }
        #endregion
    }
}
