public override void SetValue(RubyContext /*!*/ context, RubyScope scope, string /*!*/ name, object value)
        {
            switch (_id)
            {
            // regex:
            case GlobalVariableId.MatchData:
                if (scope == null)
                {
                    throw ReadOnlyError(name);
                }

                scope.GetInnerMostClosureScope().CurrentMatch = (value != null) ? RequireType <MatchData>(value, name, "MatchData") : null;
                return;

            case GlobalVariableId.MatchLastGroup:
            case GlobalVariableId.MatchPrefix:
            case GlobalVariableId.MatchSuffix:
            case GlobalVariableId.EntireMatch:
                throw ReadOnlyError(name);


            // exceptions:
            case GlobalVariableId.CurrentException:
                context.SetCurrentException(value);
                return;

            case GlobalVariableId.CurrentExceptionBacktrace:
                context.SetCurrentExceptionBacktrace(value);
                return;


            // input:
            case GlobalVariableId.LastInputLine:
                if (scope == null)
                {
                    throw ReadOnlyError(name);
                }
                scope.GetInnerMostClosureScope().LastInputLine = value;
                return;

            case GlobalVariableId.LastInputLineNumber:
                context.InputProvider.LastInputLineNumber = RequireType <int>(value, name, "Fixnum");
                return;

            case GlobalVariableId.CommandLineArguments:
            case GlobalVariableId.InputFileName:
                throw ReadOnlyError(name);

            // output:
            case GlobalVariableId.OutputStream:
                context.StandardOutput = RequireWriteProtocol(context, value, name);
                return;

            case GlobalVariableId.ErrorOutputStream:
                context.StandardErrorOutput = RequireWriteProtocol(context, value, name);
                break;

            case GlobalVariableId.InputStream:
                context.StandardInput = value;
                return;

            // separators:
            case GlobalVariableId.InputContent:
                throw ReadOnlyError(name);

            case GlobalVariableId.InputSeparator:
                context.InputSeparator = (value != null) ? RequireType <MutableString>(value, name, "String") : null;
                return;

            case GlobalVariableId.OutputSeparator:
                context.OutputSeparator = (value != null) ? RequireType <MutableString>(value, name, "String") : null;
                return;

            case GlobalVariableId.StringSeparator:
                // type not enforced:
                context.StringSeparator = value;
                return;

            case GlobalVariableId.ItemSeparator:
                context.ItemSeparator = (value != null) ? RequireType <MutableString>(value, name, "String") : null;
                return;


            // loader:
            case GlobalVariableId.LoadedFiles:
            case GlobalVariableId.LoadPath:
                throw ReadOnlyError(name);


            // misc:
            case GlobalVariableId.SafeLevel:
                context.SetSafeLevel(RequireType <int>(value, name, "Fixnum"));
                return;

            case GlobalVariableId.Verbose:
                context.Verbose = value;
                return;

            case GlobalVariableId.KCode:
                // MRI calls to_str; we don't do that, it's inconsistent with other globals.
                // If some app depends on this behavior, it will fail gracefully:
                context.SetKCode((value != null) ? RequireType <MutableString>(value, name, "String") : null);
                return;

            case GlobalVariableId.ChildProcessExitStatus:
                throw ReadOnlyError(name);

            default:
                throw Assert.Unreachable;
            }
        }