public override void eventuallyDispose()
    {
      if ( deleted )
      {
        return;
      }

      deleted = true;

      if ( nestLevel > 0 )
      {
        //-- TODO -- Determine why this is an error             throw new TclRuntimeError("dispose() called with active evals");
      }

      // Remove our association with the notifer (if we had one).

      if ( notifier != null )
      {
        notifier.release();
        notifier = null;
      }

      // Dismantle everything in the global namespace except for the
      // "errorInfo" and "errorCode" variables. These might be needed
      // later on if errors occur while deleting commands. We are careful
      // to destroy and recreate the "errorInfo" and "errorCode"
      // variables, in case they had any traces on them.
      //
      // Dismantle the namespace here, before we clear the assocData. If any
      // background errors occur here, they will be deleted below.


      // FIXME : check impl of TclTeardownNamespace
      NamespaceCmd.teardownNamespace( globalNs );

      // Delete all variables.

      TclObject errorInfoObj = null, errorCodeObj = null;

      try
      {
        errorInfoObj = getVar( "errorInfo", null, TCL.VarFlag.GLOBAL_ONLY );
      }
      catch ( TclException e )
      {
        // Do nothing when var does not exist.
      }

      if ( errorInfoObj != null )
      {
        errorInfoObj.preserve();
      }

      try
      {
        errorCodeObj = getVar( "errorCode", null, TCL.VarFlag.GLOBAL_ONLY );
      }
      catch ( TclException e )
      {
        // Do nothing when var does not exist.
      }

      if ( errorCodeObj != null )
      {
        errorCodeObj.preserve();
      }

      frame = null;
      varFrame = null;

      try
      {
        if ( errorInfoObj != null )
        {
          setVar( "errorInfo", null, errorInfoObj, TCL.VarFlag.GLOBAL_ONLY );
          errorInfoObj.release();
        }
        if ( errorCodeObj != null )
        {
          setVar( "errorCode", null, errorCodeObj, TCL.VarFlag.GLOBAL_ONLY );
          errorCodeObj.release();
        }
      }
      catch ( TclException e )
      {
        // Ignore it -- same behavior as Tcl 8.0.
      }

      // Tear down the math function table.

      expr = null;

      // Remove all the assoc data tied to this interp and invoke
      // deletion callbacks; note that a callback can create new
      // callbacks, so we iterate.

      // ATK The java code was somethink strong
      if ( assocData != null )
      {
        foreach ( AssocData data in assocData.Values )
        {
          data.disposeAssocData( this );
        }
        assocData.Clear();
      }

      // Close any remaining channels

      for ( IDictionaryEnumerator e = interpChanTable.GetEnumerator(); e.MoveNext(); )
      {
        Object key = e.Key;
        Channel chan = (Channel)e.Value;
        try
        {
          chan.close();
        }
        catch ( IOException ex )
        {
          // Ignore any IO errors
        }
      }

      // Finish deleting the global namespace.

      // FIXME : check impl of Tcl_DeleteNamespace
      NamespaceCmd.deleteNamespace( globalNs );
      globalNs = null;

      // Free up the result *after* deleting variables, since variable
      // deletion could have transferred ownership of the result string
      // to Tcl.

      frame = null;
      varFrame = null;
      resolvers = null;

      resetResult();
    }
    public Interp()
    {
      InitBlock();

      //freeProc         = null;
      errorLine = 0;

      // An empty result is used pretty often. We will use a shared
      // TclObject instance to represent the empty result so that we
      // don't need to create a new TclObject instance every time the
      // interpreter result is set to empty.

      m_nullResult = TclString.newInstance( "" );
      m_nullResult.preserve(); // Increment refCount to 1
      m_nullResult.preserve(); // Increment refCount to 2 (shared)
      m_result = TclString.newInstance( "" ); //m_nullResult; // correcponds to iPtr->objResultPtr
      m_result.preserve();

      expr = new Expression();
      nestLevel = 0;
      maxNestingDepth = 1000;

      frame = null;
      varFrame = null;

      returnCode = TCL.CompletionCode.OK;
      errorInfo = null;
      errorCode = null;

      packageTable = new Hashtable();
      packageUnknown = null;
      cmdCount = 0;
      termOffset = 0;
      resolvers = null;
      evalFlags = 0;
      scriptFile = null;
      flags = 0;
      isSafe = false;
      assocData = null;


      globalNs = null; // force creation of global ns below
      globalNs = NamespaceCmd.createNamespace( this, null, null );
      if ( globalNs == null )
      {
        throw new TclRuntimeError( "Interp(): can't create global namespace" );
      }


      // Init things that are specific to the Jacl implementation

      workingDir = new FileInfo( System.Environment.CurrentDirectory );
      noEval = 0;

      notifier = Notifier.getNotifierForThread( System.Threading.Thread.CurrentThread );
      notifier.preserve();

      randSeedInit = false;

      deleted = false;
      errInProgress = false;
      errAlreadyLogged = false;
      errCodeSet = false;

      dbg = initDebugInfo();

      slaveTable = new Hashtable();
      targetTable = new Hashtable();
      aliasTable = new Hashtable();

      // init parser variables
      Parser.init( this );
      TclParse.init( this );

      // Initialize the Global (static) channel table and the local
      // interp channel table.

      interpChanTable = TclIO.getInterpChanTable( this );

      // Sets up the variable trace for tcl_precision.

      Util.setupPrecisionTrace( this );

      // Create the built-in commands.

      createCommands();

      try
      {
        // Set up tcl_platform, tcl_version, tcl_library and other
        // global variables.

        setVar( "tcl_platform", "platform", "windows", TCL.VarFlag.GLOBAL_ONLY );
        setVar( "tcl_platform", "byteOrder", "bigEndian", TCL.VarFlag.GLOBAL_ONLY );

        setVar( "tcl_platform", "os", Environment.OSVersion.Platform.ToString(), TCL.VarFlag.GLOBAL_ONLY );
        setVar( "tcl_platform", "osVersion", Environment.OSVersion.Version.ToString(), TCL.VarFlag.GLOBAL_ONLY );
        setVar( "tcl_platform", "machine", Util.tryGetSystemProperty( "os.arch", "?" ), TCL.VarFlag.GLOBAL_ONLY );

        setVar( "tcl_version", TCL_VERSION, TCL.VarFlag.GLOBAL_ONLY );
        setVar( "tcl_patchLevel", TCL_PATCH_LEVEL, TCL.VarFlag.GLOBAL_ONLY );
        setVar( "tcl_library", "resource:/tcl/lang/library", TCL.VarFlag.GLOBAL_ONLY );
        if ( Util.Windows )
        {
          setVar( "tcl_platform", "host_platform", "windows", TCL.VarFlag.GLOBAL_ONLY );
        }
        else if ( Util.Mac )
        {
          setVar( "tcl_platform", "host_platform", "macintosh", TCL.VarFlag.GLOBAL_ONLY );
        }
        else
        {
          setVar( "tcl_platform", "host_platform", "unix", TCL.VarFlag.GLOBAL_ONLY );
        }

        // Create the env array an populated it with proper
        // values.

        Env.initialize( this );

        // Register Tcl's version number. Note: This MUST be 
        // done before the call to evalResource, otherwise
        // calls to "package require tcl" will fail.

        pkgProvide( "Tcl", TCL_VERSION );

        // Source the init.tcl script to initialize auto-loading.

        evalResource( "/tcl/lang/library/init.tcl" );
      }
      catch ( TclException e )
      {
        System.Diagnostics.Debug.WriteLine( getResult().ToString() );
        SupportClass.WriteStackTrace( e, Console.Error );
        throw new TclRuntimeError( "unexpected TclException: " + e.Message, e );
      }
    }