Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
BEGIN LICENSE BLOCK ***** Version: CPL 1.0/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Common Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.eclipse.org/legal/cpl-v10.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. Copyright (C) 2002 Benoit Cerrina <b.cerrina@wanadoo.fr> Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se> Copyright (C) 2002-2004 Jan Arne Petersen <jpetersen@uni-bonn.de> Copyright (C) 2004 Charles O Nutter <headius@headius.com> Copyright (C) 2004 Thomas E Enebo <enebo@acm.org> Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de> Copyright (C) 2006 Tim Azzopardi <tim@tigerfive.com> Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com> Copyright (C) 2006 Michael Studman <codehaus@michaelstudman.com> Copyright (C) 2008 Joseph LaFata <joe@quibb.org> Alternatively, the contents of this file may be used under the terms of either of the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to use your version of this file under the terms of the CPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL or the LGPL. If you do not delete the provisions above, a recipient may use your version of this file under the terms of any one of the CPL, the GPL or the LGPL. END LICENSE BLOCK ***
 
 package org.jruby;
 
 
 import java.util.Map;

This class initializes global variables and constants.

Author(s):
jpetersen
 
 public class RubyGlobal {
     public static void createGlobals(ThreadContext contextRuby runtime) {
         GlobalVariables globals = runtime.getGlobalVariables();
 
         runtime.defineGlobalConstant("TOPLEVEL_BINDING"runtime.newBinding());
         
         runtime.defineGlobalConstant("TRUE"runtime.getTrue());
         runtime.defineGlobalConstant("FALSE"runtime.getFalse());
         runtime.defineGlobalConstant("NIL"runtime.getNil());
         
         // define ARGV and $* for this runtime
         RubyArray argvArray = runtime.newArray();
         String[] argv = runtime.getInstanceConfig().getArgv();
 
         for (String arg : argv) {
             argvArray.append(RubyString.newInternalFromJavaExternal(runtimearg));
         }
 
         runtime.defineGlobalConstant("ARGV"argvArray);
         globals.define("$*"new ValueAccessor(argvArray));
 
         IAccessor d = new ValueAccessor(runtime.newString(
                 runtime.getInstanceConfig().displayedFileName()));
         globals.define("$PROGRAM_NAME"d);
         globals.define("$0"d);
 
         // Version information:
         IRubyObject version = null;
         IRubyObject patchlevel = null;
         IRubyObject release = runtime.newString(.).freeze(context);
         IRubyObject platform = runtime.newString(.).freeze(context);
        IRubyObject engine = runtime.newString(.).freeze(context);
        switch (runtime.getInstanceConfig().getCompatVersion()) {
        case :
            version = runtime.newString(.).freeze(context);
            patchlevel = runtime.newFixnum(.);
            break;
        case :
            version = runtime.newString(.).freeze(context);
            patchlevel = runtime.newFixnum(.);
            break;
        case :
            version = runtime.newString(.).freeze(context);
            patchlevel = runtime.newFixnum(.);
            break;
        }
        runtime.defineGlobalConstant("RUBY_VERSION"version);
        runtime.defineGlobalConstant("RUBY_PATCHLEVEL"patchlevel);
        runtime.defineGlobalConstant("RUBY_RELEASE_DATE"release);
        runtime.defineGlobalConstant("RUBY_PLATFORM"platform);
        runtime.defineGlobalConstant("RUBY_ENGINE"engine);
        IRubyObject description = runtime.newString(OutputStrings.getVersionString(runtime.getInstanceConfig().getCompatVersion())).freeze(context);
        runtime.defineGlobalConstant("RUBY_DESCRIPTION"description);
        IRubyObject copyright = runtime.newString(OutputStrings.getCopyrightString()).freeze(context);
        runtime.defineGlobalConstant("RUBY_COPYRIGHT"copyright);
        runtime.defineGlobalConstant("VERSION"version);
        runtime.defineGlobalConstant("RELEASE_DATE"release);
        runtime.defineGlobalConstant("PLATFORM"platform);
        
        IRubyObject jrubyVersion = runtime.newString(.).freeze(context);
        IRubyObject jrubyRevision = runtime.newString(.).freeze(context);
        runtime.defineGlobalConstant("JRUBY_VERSION"jrubyVersion);
        runtime.defineGlobalConstant("JRUBY_REVISION"jrubyRevision);
        if (runtime.is1_9()) {
            // needs to be a fixnum, but our revision is a sha1 hash from git
            runtime.defineGlobalConstant("RUBY_REVISION"runtime.newFixnum(.));
            
            RubyInstanceConfig.Verbosity verbosity = runtime.getInstanceConfig().getVerbosity();
            runtime.defineVariable(new WarningGlobalVariable(runtime"$-W"verbosity));
        }
        final GlobalVariable kcodeGV
        if (runtime.is1_9()) {
            kcodeGV = new NonEffectiveGlobalVariable(runtime"$KCODE"runtime.getNil());
        } else {
            kcodeGV = new KCodeGlobalVariable(runtime"$KCODE"runtime.newString("NONE"));
        }
        runtime.defineVariable(kcodeGV);
        runtime.defineVariable(new GlobalVariable.Copy(runtime"$-K"kcodeGV));
        IRubyObject defaultRS = runtime.newString(runtime.getInstanceConfig().getRecordSeparator()).freeze(context);
        GlobalVariable rs = new StringGlobalVariable(runtime"$/"defaultRS);
        runtime.defineVariable(rs);
        runtime.setRecordSeparatorVar(rs);
        globals.setDefaultSeparator(defaultRS);
        runtime.defineVariable(new StringGlobalVariable(runtime"$\\"runtime.getNil()));
        runtime.defineVariable(new StringGlobalVariable(runtime"$,"runtime.getNil()));
        runtime.defineVariable(new LineNumberGlobalVariable(runtime"$."));
        runtime.defineVariable(new LastlineGlobalVariable(runtime"$_"));
        runtime.defineVariable(new LastExitStatusVariable(runtime"$?"));
        runtime.defineVariable(new ErrorInfoGlobalVariable(runtime"$!"runtime.getNil()));
        runtime.defineVariable(new NonEffectiveGlobalVariable(runtime"$="runtime.getFalse()));
        if(runtime.getInstanceConfig().getInputFieldSeparator() == null) {
            runtime.defineVariable(new GlobalVariable(runtime"$;"runtime.getNil()));
        } else {
            runtime.defineVariable(new GlobalVariable(runtime"$;", RubyRegexp.newRegexp(runtimeruntime.getInstanceConfig().getInputFieldSeparator(), new RegexpOptions())));
        }
        
        RubyInstanceConfig.Verbosity verbose = runtime.getInstanceConfig().getVerbosity();
        IRubyObject verboseValue = null;
        if (verbose == ..) {
            verboseValue = runtime.getNil();
        } else if(verbose == ..) {
            verboseValue = runtime.getTrue();
        } else {
            verboseValue = runtime.getFalse();
        }
        runtime.defineVariable(new VerboseGlobalVariable(runtime"$VERBOSE"verboseValue));
        runtime.defineVariable(new VerboseGlobalVariable(runtime"$-v"verboseValue));
        runtime.defineVariable(new VerboseGlobalVariable(runtime"$-w"verboseValue));
        
        IRubyObject debug = runtime.newBoolean(runtime.getInstanceConfig().isDebug());
        runtime.defineVariable(new DebugGlobalVariable(runtime"$DEBUG"debug));
        runtime.defineVariable(new DebugGlobalVariable(runtime"$-d"debug));
        runtime.defineVariable(new SafeGlobalVariable(runtime"$SAFE"));
        runtime.defineVariable(new BacktraceGlobalVariable(runtime"$@"));
        IRubyObject stdin = new RubyIO(runtime.);
        IRubyObject stdout = new RubyIO(runtime.);
        IRubyObject stderr = new RubyIO(runtime.);
        runtime.defineVariable(new InputGlobalVariable(runtime"$stdin"stdin));
        runtime.defineVariable(new OutputGlobalVariable(runtime"$stdout"stdout));
        globals.alias("$>""$stdout");
        if (!runtime.is1_9()) globals.alias("$defout""$stdout");
        runtime.defineVariable(new OutputGlobalVariable(runtime"$stderr"stderr));
        if (!runtime.is1_9()) globals.alias("$deferr""$stderr");
        runtime.defineGlobalConstant("STDIN"stdin);
        runtime.defineGlobalConstant("STDOUT"stdout);
        runtime.defineGlobalConstant("STDERR"stderr);
        runtime.defineVariable(new LoadedFeatures(runtime"$\""));
        runtime.defineVariable(new LoadedFeatures(runtime"$LOADED_FEATURES"));
        runtime.defineVariable(new LoadPath(runtime"$:"));
        runtime.defineVariable(new LoadPath(runtime"$-I"));
        runtime.defineVariable(new LoadPath(runtime"$LOAD_PATH"));
        
        runtime.defineVariable(new MatchMatchGlobalVariable(runtime"$&"));
        runtime.defineVariable(new PreMatchGlobalVariable(runtime"$`"));
        runtime.defineVariable(new PostMatchGlobalVariable(runtime"$'"));
        runtime.defineVariable(new LastMatchGlobalVariable(runtime"$+"));
        runtime.defineVariable(new BackRefGlobalVariable(runtime"$~"));
        // On platforms without a c-library accessable through JNA, getpid will return hashCode 
        // as $$ used to. Using $$ to kill processes could take down many runtimes, but by basing
        // $$ on getpid() where available, we have the same semantics as MRI.
        globals.defineReadonly("$$"new PidAccessor(runtime));
        // after defn of $stderr as the call may produce warnings
        defineGlobalEnvConstants(runtime);
        
        // Fixme: Do we need the check or does Main.java not call this...they should consolidate 
        if (globals.get("$*").isNil()) {
            globals.defineReadonly("$*"new ValueAccessor(runtime.newArray()));
        }
        
        globals.defineReadonly("$-p",
                new ValueAccessor(runtime.newBoolean(runtime.getInstanceConfig().isAssumePrinting())));
        globals.defineReadonly("$-a",
                new ValueAccessor(runtime.newBoolean(runtime.getInstanceConfig().isSplit())));
        globals.defineReadonly("$-l",
                new ValueAccessor(runtime.newBoolean(runtime.getInstanceConfig().isProcessLineEnds())));
        // ARGF, $< object
        RubyArgsFile.initArgsFile(runtime);
        // Define aliases originally in the "English.rb" stdlib
        globals.alias("$ERROR_INFO""$!");
        globals.alias("$ERROR_POSITION""$@");
        globals.alias("$FS""$;");
        globals.alias("$FIELD_SEPARATOR""$;");
        globals.alias("$OFS""$,");
        globals.alias("$OUTPUT_FIELD_SEPARATOR""$,");
        globals.alias("$RS""$/");
        globals.alias("$INPUT_RECORD_SEPARATOR""$/");
        globals.alias("$ORS""$\\");
        globals.alias("$OUTPUT_RECORD_SEPARATOR""$\\");
        globals.alias("$NR""$.");
        globals.alias("$INPUT_LINE_NUMBER""$.");
        globals.alias("$LAST_READ_LINE""$_");
        globals.alias("$DEFAULT_OUTPUT""$>");
        globals.alias("$DEFAULT_INPUT""$<");
        globals.alias("$PID""$$");
        globals.alias("$PROCESS_ID""$$");
        globals.alias("$CHILD_STATUS""$?");
        globals.alias("$LAST_MATCH_INFO""$~");
        globals.alias("$IGNORECASE""$=");
        globals.alias("$ARGV""$*");
        globals.alias("$MATCH""$&");
        globals.alias("$PREMATCH""$`");
        globals.alias("$POSTMATCH""$'");
        globals.alias("$LAST_PAREN_MATCH""$+");
    }
    private static void defineGlobalEnvConstants(Ruby runtime) {
    	Map environmentVariableMap = null;
    	OSEnvironment environment = new OSEnvironment();
        environmentVariableMap = environment.getEnvironmentVariableMap(runtime);
    	if (environmentVariableMap == null) {
            // if the environment variables can't be obtained, define an empty ENV
    		environmentVariableMap = new HashMap();
    	}
                                                       environmentVariableMap
                                                       runtime.getNil(),
                                                       runtime.getInstanceConfig().isNativeEnabled() && 
                                                           runtime.getInstanceConfig().isUpdateNativeENVEnabled() );
        runtime.defineGlobalConstant("ENV"env);
        runtime.setENV(env);
        // Define System.getProperties() in ENV_JAVA
        Map systemProps = environment.getSystemPropertiesMap(runtime);
        RubyHash systemPropsHash = new ReadOnlySystemPropertiesHash(
                runtimesystemPropsruntime.getNil());
        systemPropsHash.setFrozen(true);
        runtime.defineGlobalConstant("ENV_JAVA"systemPropsHash);
    }

    
Obligate string-keyed and string-valued hash, used for ENV. On Windows, the keys are case-insensitive for ENV
    public static class CaseInsensitiveStringOnlyRubyHash extends StringOnlyRubyHash {
        public CaseInsensitiveStringOnlyRubyHash(Ruby runtimeMap valueMapIRubyObject defaultValueboolean updateRealENV) {
            super(runtimevalueMapdefaultValueupdateRealENV);
        }
        @Override
        public IRubyObject op_aref(ThreadContext contextIRubyObject key) {
            return case_aware_op_aref(contextkeyfalse);
        }
        @Override
        public IRubyObject op_aset(ThreadContext contextIRubyObject keyIRubyObject value) {
            return case_aware_op_aset(contextkeyvaluefalse);
        }
        @JRubyMethod
        @Override
        public IRubyObject to_s(){
            return getRuntime().newString("ENV");
        }
    }

    
A Pseudo-hash whose keys and values are required to be Strings. On all platforms, the keys are case-sensitive. Used for ENV_JAVA.
    public static class StringOnlyRubyHash extends RubyHash {
        // This is an ugly hack.  Windows ENV map processing all happens in this
        // class and not in the caseinsensitive hash.  In order to not refactor
        // both of these maps we will pass in a flag to specify whether we want
        // the op_aset to also update the real ENV map via setenv/unsetenv.
        private boolean updateRealENV;
        public StringOnlyRubyHash(Ruby runtimeMap valueMapIRubyObject defaultValueboolean updateRealENV) {
            super(runtimevalueMapdefaultValue);
            this. = updateRealENV;
        }
        public StringOnlyRubyHash(Ruby runtimeMap valueMapIRubyObject defaultValue) {
            this(runtimevalueMapdefaultValuefalse);
        }
        @Override
        public IRubyObject op_aref(ThreadContext contextIRubyObject key) {
            return case_aware_op_aref(contextkeytrue);
        }
        @Override
        public RubyHash to_hash() {
            Ruby runtime = getRuntime();
            RubyHash hash = RubyHash.newHash(runtime);
            hash.replace(runtime.getCurrentContext(), this);
            return hash;
        }
        @Override
        public IRubyObject op_aset(ThreadContext contextIRubyObject keyIRubyObject value) {
            return case_aware_op_aset(contextkeyvaluetrue);
        }
        @Override
        public IRubyObject op_aset19(ThreadContext contextIRubyObject keyIRubyObject value) {
            return op_aset(contextkeyvalue);
        }
        protected IRubyObject case_aware_op_aref(ThreadContext contextIRubyObject keyboolean caseSensitive) {
            if (! caseSensitive) {
                key = getCorrectKey(keycontext);
            }
            return super.op_aref(contextkey);
        }
        protected IRubyObject case_aware_op_aset(ThreadContext contextIRubyObject keyIRubyObject valueboolean caseSensitive) {
            if (!key.respondsTo("to_str")) {
                throw getRuntime().newTypeError("can't convert " + key.getMetaClass() + " into String");
            }
            if (!value.respondsTo("to_str") && !value.isNil()) {
                throw getRuntime().newTypeError("can't convert " + value.getMetaClass() + " into String");
            }
            if (! caseSensitive) {
                key = getCorrectKey(keycontext);
            }
            if (value.isNil()) {
                return super.delete(contextkey....);
            }
            IRubyObject keyAsStr = normalizeEnvString(RuntimeHelpers.invoke(contextkey"to_str"));
            IRubyObject valueAsStr = value.isNil() ? getRuntime().getNil() :
                    normalizeEnvString(RuntimeHelpers.invoke(contextvalue"to_str"));
            if () {
                POSIX posix = getRuntime().getPosix();
                String keyAsJava = keyAsStr.asJavaString();
                // libc (un)setenv is not reentrant, so we need to synchronize across the entire JVM (JRUBY-5933)
                if (valueAsStr == getRuntime().getNil()) {
                    synchronized (Object.class) { posix.unsetenv(keyAsJava); }
                } else {
                    synchronized (Object.class) { posix.setenv(keyAsJavavalueAsStr.asJavaString(), 1); }
                }
            }
            return super.op_aset(contextkeyAsStrvalueAsStr);
        }
        private RubyString getCorrectKey(IRubyObject keyThreadContext context) {
            RubyString originalKey = key.convertToString();
            RubyString actualKey = originalKey;
            Ruby runtime = context.runtime;
            if (.) {
                // this is a rather ugly hack, but similar to MRI. See hash.c:ruby_setenv and similar in MRI
                // we search all keys for a case-insensitive match, and use that
                RubyArray keys = super.keys();
                for (int i = 0; i < keys.size(); i++) {
                    RubyString candidateKey = keys.eltInternal(i).convertToString();
                    if (candidateKey.casecmp(contextoriginalKey).op_equal(context, RubyFixnum.zero(runtime)).isTrue()) {
                        actualKey = candidateKey;
                        break;
                    }
                }
            }
            return actualKey;
        }
        private IRubyObject normalizeEnvString(IRubyObject str) {
            if (str instanceof RubyString) {
                Encoding enc = getRuntime().getEncodingService().getLocaleEncoding();
                RubyString newStr = getRuntime().newString(new ByteList(str.toString().getBytes(), enc));
                newStr.setFrozen(true);
                return newStr;
            } else {
                return str;
            }
        }
    }
    private static class ReadOnlySystemPropertiesHash extends StringOnlyRubyHash {
        public ReadOnlySystemPropertiesHash(Ruby runtimeMap valueMapIRubyObject defaultValueboolean updateRealENV) {
            super(runtimevalueMapdefaultValueupdateRealENV);
        }
        public ReadOnlySystemPropertiesHash(Ruby runtimeMap valueMapIRubyObject defaultValue) {
            this(runtimevalueMapdefaultValuefalse);
        }
        public void modify() {
            if (isFrozen()) {
                throw getRuntime().newTypeError("ENV_JAVA is not writable until you require 'java'");
            }
        }
    }
    private static class NonEffectiveGlobalVariable extends GlobalVariable {
        public NonEffectiveGlobalVariable(Ruby runtimeString nameIRubyObject value) {
            super(runtimenamevalue);
        }
        @Override
        public IRubyObject set(IRubyObject value) {
            .getWarnings().warn(."warning: variable " +  + " is no longer effective; ignored");
            return value;
        }
        @Override
        public IRubyObject get() {
            .getWarnings().warn(."warning: variable " +  + " is no longer effective");
            return ;
        }
    }
    private static class LastExitStatusVariable extends GlobalVariable {
        public LastExitStatusVariable(Ruby runtimeString name) {
            super(runtimenameruntime.getNil());
        }
        
        @Override
        public IRubyObject get() {
            IRubyObject lastExitStatus = .getCurrentContext().getLastExitStatus();
            return lastExitStatus == null ? .getNil() : lastExitStatus;
        }
        
        @Override
        public IRubyObject set(IRubyObject lastExitStatus) {
            throw .newNameError("$? is a read-only variable""$?");
        }
    }
    private static class MatchMatchGlobalVariable extends GlobalVariable {
        public MatchMatchGlobalVariable(Ruby runtimeString name) {
            super(runtimenameruntime.getNil());
        }
        
        @Override
        public IRubyObject get() {
            return RubyRegexp.last_match(.getCurrentContext().getCurrentScope().getBackRef());
        }
    }
    private static class PreMatchGlobalVariable extends GlobalVariable {
        public PreMatchGlobalVariable(Ruby runtimeString name) {
            super(runtimenameruntime.getNil());
        }
        
        @Override
        public IRubyObject get() {
            return RubyRegexp.match_pre(.getCurrentContext().getCurrentScope().getBackRef());
        }
    }
    private static class PostMatchGlobalVariable extends GlobalVariable {
        public PostMatchGlobalVariable(Ruby runtimeString name) {
            super(runtimenameruntime.getNil());
        }
        
        @Override
        public IRubyObject get() {
            return RubyRegexp.match_post(.getCurrentContext().getCurrentScope().getBackRef());
        }
    }
    private static class LastMatchGlobalVariable extends GlobalVariable {
        public LastMatchGlobalVariable(Ruby runtimeString name) {
            super(runtimenameruntime.getNil());
        }
        
        @Override
        public IRubyObject get() {
            return RubyRegexp.match_last(.getCurrentContext().getCurrentScope().getBackRef());
        }
    }
    private static class BackRefGlobalVariable extends GlobalVariable {
        public BackRefGlobalVariable(Ruby runtimeString name) {
            super(runtimenameruntime.getNil());
        }
        
        @Override
        public IRubyObject get() {
            return RuntimeHelpers.getBackref(.getCurrentContext());
        }
        @Override
        public IRubyObject set(IRubyObject value) {
            RuntimeHelpers.setBackref(.getCurrentContext(), value);
            return value;
        }
    }
    // Accessor methods.
    private static class LineNumberGlobalVariable extends GlobalVariable {
        public LineNumberGlobalVariable(Ruby runtimeString name) {
            super(runtimenamenull);
        }
        @Override
        public IRubyObject set(IRubyObject value) {
            int line = (int)value.convertToInteger().getLongValue();
            .setCurrentLine(line);
            RubyArgsFile.setCurrentLineNumber(.getArgsFile(), line);
            return value;
        }
        @Override
        public IRubyObject get() {
            return .newFixnum(.getCurrentLine());
        }
    }
    private static class ErrorInfoGlobalVariable extends GlobalVariable {
        public ErrorInfoGlobalVariable(Ruby runtimeString nameIRubyObject value) {
            super(runtimenamenull);
            set(value);
        }
        @Override
        public IRubyObject set(IRubyObject value) {
            if (!value.isNil() &&
                    !.getException().isInstance(value) &&
                    !(JavaUtil.isJavaObject(value) && JavaUtil.unwrapJavaObject(valueinstanceof Throwable)) {
                throw .newTypeError("assigning non-exception to $!");
            }
            
            return .getCurrentContext().setErrorInfo(value);
        }
        @Override
        public IRubyObject get() {
            return .getCurrentContext().getErrorInfo();
        }
    }
    // FIXME: move out of this class!
    public static class StringGlobalVariable extends GlobalVariable {
        public StringGlobalVariable(Ruby runtimeString nameIRubyObject value) {
            super(runtimenamevalue);
        }
        @Override
        public IRubyObject set(IRubyObject value) {
            if (!value.isNil() && ! (value instanceof RubyString)) {
                throw .newTypeError("value of " + name() + " must be a String");
            }
            return super.set(value);
        }
    }
    public static class KCodeGlobalVariable extends GlobalVariable {
        public KCodeGlobalVariable(Ruby runtimeString nameIRubyObject value) {
            super(runtimenamevalue);
        }
        @Override
        public IRubyObject get() {
            return .getKCode().kcode();
        }
        @Override
        public IRubyObject set(IRubyObject value) {
            .setKCode(KCode.create(value.convertToString().toString()));
            return value;
        }
    }
    private static class SafeGlobalVariable extends GlobalVariable {
        public SafeGlobalVariable(Ruby runtimeString name) {
            super(runtimenamenull);
        }
        @Override
        public IRubyObject get() {
            return RubyFixnum.zero();
        }
        @Override
        public IRubyObject set(IRubyObject value) {
            .getWarnings().warnOnce(."SAFE levels are not supported in JRuby");
            return RubyFixnum.zero();
        }
    }
    private static class VerboseGlobalVariable extends GlobalVariable {
        public VerboseGlobalVariable(Ruby runtimeString nameIRubyObject initialValue) {
            super(runtimenameinitialValue);
            set(initialValue);
        }
        
        @Override
        public IRubyObject get() {
            return .getVerbose();
        }
        @Override
        public IRubyObject set(IRubyObject newValue) {
            if (newValue.isNil()) {
                .setVerbose(newValue);
            } else {
                .setVerbose(.newBoolean(newValue.isTrue()));
            }
            return newValue;
        }
    }
    
    private static class WarningGlobalVariable extends ReadonlyGlobalVariable {
        public WarningGlobalVariable(Ruby runtimeString nameRubyInstanceConfig.Verbosity verbosity) {
            super(runtimename,
                    verbosity == ..   ? RubyFixnum.newFixnum(runtime, 0) :
                    verbosity == .. ? RubyFixnum.newFixnum(runtime, 1) :
                    verbosity == ..  ? RubyFixnum.newFixnum(runtime, 2) :
                    runtime.getNil()
                    );
        }
    }
    private static class DebugGlobalVariable extends GlobalVariable {
        public DebugGlobalVariable(Ruby runtimeString nameIRubyObject initialValue) {
            super(runtimenameinitialValue);
            set(initialValue);
        }
        @Override
        public IRubyObject get() {
            return .getDebug();
        }
        @Override
        public IRubyObject set(IRubyObject newValue) {
            if (newValue.isNil()) {
                .setDebug(newValue);
            } else {
                .setDebug(.newBoolean(newValue.isTrue()));
            }
            return newValue;
        }
    }
    private static class BacktraceGlobalVariable extends GlobalVariable {
        public BacktraceGlobalVariable(Ruby runtimeString name) {
            super(runtimenamenull);
        }
        @Override
        public IRubyObject get() {
            IRubyObject errorInfo = .getGlobalVariables().get("$!");
            IRubyObject backtrace = errorInfo.isNil() ? .getNil() : errorInfo.callMethod(errorInfo.getRuntime().getCurrentContext(), "backtrace");
            //$@ returns nil if $!.backtrace is not an array
            if (!(backtrace instanceof RubyArray)) {
                backtrace = .getNil();
            }
            return backtrace;
        }
        @Override
        public IRubyObject set(IRubyObject value) {
            if (.getGlobalVariables().get("$!").isNil()) {
                throw .newArgumentError("$! not set.");
            }
            .getGlobalVariables().get("$!").callMethod(value.getRuntime().getCurrentContext(), "set_backtrace"value);
            return value;
        }
    }
    private static class LastlineGlobalVariable extends GlobalVariable {
        public LastlineGlobalVariable(Ruby runtimeString name) {
            super(runtimenamenull);
        }
        @Override
        public IRubyObject get() {
            return RuntimeHelpers.getLastLine(.getCurrentContext());
        }
        @Override
        public IRubyObject set(IRubyObject value) {
            RuntimeHelpers.setLastLine(.getCurrentContext(), value);
            return value;
        }
    }
    public static class InputGlobalVariable extends GlobalVariable {
        public InputGlobalVariable(Ruby runtimeString nameIRubyObject value) {
            super(runtimenamevalue);
        }
        @Override
        public IRubyObject set(IRubyObject value) {
            if (value == get()) {
                return value;
            }
            
            return super.set(value);
        }
    }
    public static class OutputGlobalVariable extends GlobalVariable {
        public OutputGlobalVariable(Ruby runtimeString nameIRubyObject value) {
            super(runtimenamevalue);
        }
        @Override
        public IRubyObject set(IRubyObject value) {
            if (value == get()) {
                return value;
            }
            if (value instanceof RubyIO) {
                RubyIO io = (RubyIO)value;
                
                // HACK: in order to have stdout/err act like ttys and flush always,
                // we set anything assigned to stdout/stderr to sync
                try {
                    io.getOpenFile().getWriteStreamSafe().setSync(true);
                } catch (BadDescriptorException e) {
                    throw .newErrnoEBADFError();
                }
            }
            if (!value.respondsTo("write")) {
                throw .newTypeError(name() + " must have write method, " +
                                    value.getType().getName() + " given");
            }
            return super.set(value);
        }
    }
    private static class LoadPath extends ReadonlyGlobalVariable {
        public LoadPath(Ruby runtimeString name) {
            super(runtimenamenull);
        }
        
        
        @Override
        public IRubyObject get() {
            return .getLoadService().getLoadPath();
        }
    }
    private static class LoadedFeatures extends ReadonlyGlobalVariable {
        public LoadedFeatures(Ruby runtimeString name) {
            super(runtimenamenull);
        }
        
        
        @Override
        public IRubyObject get() {
            return .getLoadService().getLoadedFeatures();
        }
    }

    
A special accessor for getpid, to avoid loading the posix subsystem until it is needed.
    private static final class PidAccessor implements IAccessor {
        private final Ruby runtime;
        private volatile IRubyObject pid = null;
        public PidAccessor(Ruby runtime) {
            this. = runtime;
        }
        public IRubyObject getValue() {
            return  != null ?  : ( = .newFixnum(.getPosix().getpid()));
        }
        public IRubyObject setValue(IRubyObject newValue) {
            throw .newRuntimeError("cannot assign to $$");
        }
    }