SquirrelJME/SquirrelJME

View on GitHub
emulators/springcoat-vm/src/main/java/cc/squirreljme/vm/springcoat/MLERuntime.java

Summary

Maintainability
A
0 mins
Test Coverage
// -*- Mode: Java; indent-tabs-mode: t; tab-width: 4 -*-
// ---------------------------------------------------------------------------
// SquirrelJME
//     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
// ---------------------------------------------------------------------------
// SquirrelJME is under the Mozilla Public License Version 2.0.
// See license.mkd for licensing and copyright information.
// ---------------------------------------------------------------------------

package cc.squirreljme.vm.springcoat;

import cc.squirreljme.jvm.mle.RuntimeShelf;
import cc.squirreljme.jvm.mle.constants.BuiltInEncodingType;
import cc.squirreljme.jvm.mle.constants.BuiltInLocaleType;
import cc.squirreljme.jvm.mle.constants.ByteOrderType;
import cc.squirreljme.jvm.mle.constants.MemoryProfileType;
import cc.squirreljme.jvm.mle.constants.PhoneModelType;
import cc.squirreljme.jvm.mle.constants.VMDescriptionType;
import cc.squirreljme.jvm.mle.constants.VMStatisticType;
import cc.squirreljme.jvm.mle.constants.VMType;
import cc.squirreljme.jvm.mle.exceptions.MLECallError;
import cc.squirreljme.runtime.cldc.lang.LineEndingUtils;
import cc.squirreljme.vm.springcoat.exceptions.SpringMLECallError;

/**
 * Functions for {@link MLERuntime}.
 *
 * @since 2020/06/18
 */
public enum MLERuntime
    implements MLEFunction
{
    /** {@link RuntimeShelf#byteOrder()}. */
    BYTE_ORDER("byteOrder:()I")
    {
        /**
         * {@inheritDoc}
         * @since 2021/02/09
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            // SpringCoat is always big endian
            return ByteOrderType.BIG_ENDIAN;
        }
    },
    
    /** {@link RuntimeShelf#currentTimeMillis()}. */
    CURRENT_TIME_MILLIS("currentTimeMillis:()J")
    {
        /**
         * {@inheritDoc}
         * @since 2020/06/18
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            return System.currentTimeMillis();
        }
    },
    
    /** {@link RuntimeShelf#encoding()}. */
    ENCODING("encoding:()I")
    {
        /**
         * {@inheritDoc}
         * @since 2020/06/18
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            return BuiltInEncodingType.UTF8;
        }
    },
    
    /** {@link RuntimeShelf#exit(int)}. */
    EXIT("exit:(I)V")
    {
        /**
         * {@inheritDoc}
         * @since 2020/06/18
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            __thread.machine.exit((int)__args[0]);
            return null;
        }
    },
    
    /** {@link RuntimeShelf#garbageCollect()}. */
    GARBAGE_COLLECT("garbageCollect:()V")
    {
        /**
         * {@inheritDoc}
         * @since 2021/01/04
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            // Use the system GC since it is the only suggestion we can make
            Runtime.getRuntime().gc();
            return null;
        }
    },
    
    /** {@link RuntimeShelf#lineEnding()}. */
    LINE_ENDING("lineEnding:()I")
    {
        /**
         * {@inheritDoc}
         * @since 2020/06/18
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            return LineEndingUtils.toType(
                System.getProperty("line.separator"));
        }
    },
    
    /** {@link RuntimeShelf#locale()}. */
    LOCALE("locale:()I")
    {
        /**
         * {@inheritDoc}
         * @since 2020/06/18
         */
        @SuppressWarnings("SwitchStatementWithTooFewBranches")
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            String country = System.getProperty("user.country",
                "unknown");
            String lang = System.getProperty("user.language",
                "unknown");
            
            switch (country)
            {
                case "US":
                    switch (lang)
                    {
                        case "en":
                            return BuiltInLocaleType.ENGLISH_US;
                    }
                    return BuiltInLocaleType.UNSPECIFIED;
                
                default:
                    return BuiltInLocaleType.UNSPECIFIED;
            }
        }
    },
    
    /** {@link RuntimeShelf#memoryProfile()}. */
    MEMORY_PROFILE("memoryProfile:()I")
    {
        /**
         * {@inheritDoc}
         * @since 2021/02/19
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            // No memory concerns
            return MemoryProfileType.NORMAL;
        }
    },
    
    /** {@link RuntimeShelf#nanoTime()}. */
    NANO_TIME("nanoTime:()J")
    {
        /**
         * {@inheritDoc}
         * @since 2020/06/18
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            return System.nanoTime();
        }
    },
    
    /** {@link RuntimeShelf#phoneModel()}. */
    PHONE_MODEL("phoneModel:()I")
    {
        /**
         * {@inheritDoc}
         * @since 2022/02/14
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            // Just be a generic model
            return PhoneModelType.GENERIC;
        }
    },
    
    /** {@link RuntimeShelf#systemEnv(String)}. */
    SYSTEM_ENV("systemEnv:(Ljava/lang/String;)" +
        "Ljava/lang/String;")
    {
        /**
         * {@inheritDoc}
         * @since 2023/02/02
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            String key = __thread
                .<String>asNativeObject(String.class, __args[0]);
            
            if (key == null)
                throw new SpringMLECallError("Null key.");
            
            return __thread.asVMObject(RuntimeShelf.systemEnv(key));
        }
    },
    
    /** {@link RuntimeShelf#systemProperty(String)}. */
    SYSTEM_PROPERTY("systemProperty:(Ljava/lang/String;)" +
        "Ljava/lang/String;")
    {
        /**
         * {@inheritDoc}
         * @since 2020/06/18
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            String key = __thread
                .<String>asNativeObject(String.class, __args[0]);
            
            if (key == null)
                throw new SpringMLECallError("Null key.");
            
            return __thread.machine._sysproperties.get(key);
        }
    },
    
    /** {@link RuntimeShelf#vmDescription(int)}. */
    VM_DESCRIPTION("vmDescription:(I)Ljava/lang/String;")
    {
        /**
         * {@inheritDoc}
         * @since 2020/06/18
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            int index = (int)__args[0];
            if (index < 0 || index >= VMDescriptionType.NUM_TYPES)
                throw new SpringMLECallError(
                    "Index out of range: " + index);
            
            switch (index)
            {
                case VMDescriptionType.EXECUTABLE_PATH:
                    return null;
                
                case VMDescriptionType.OS_ARCH:
                    return "springcoat/" + System.getProperty("os.arch");
                    
                case VMDescriptionType.OS_NAME:
                    return System.getProperty("os.name");
                
                case VMDescriptionType.OS_VERSION:
                    return System.getProperty("os.version");
                
                case VMDescriptionType.VM_EMAIL:
                    return "xer@multiphasicapps.net";
                    
                case VMDescriptionType.VM_NAME:
                    return __thread.machine.tasks.vmName();
                
                case VMDescriptionType.VM_VERSION:
                    return __thread.machine.tasks.vmVersion();
                
                case VMDescriptionType.VM_URL:
                    return "https://squirreljme.cc/";
                    
                case VMDescriptionType.VM_VENDOR:
                    return "Stephanie Gawroriski";
            }
            
            return null;
        }
    },
    
    /** {@link RuntimeShelf#vmStatistic(int)}. */
    VM_STATISTIC("vmStatistic:(I)J")
    {
        /**
         * {@inheritDoc}
         * @since 2020/06/18
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            int index = (int)__args[0];
            if (index < 0 || index >= VMStatisticType.NUM_STATISTICS)
                throw new SpringMLECallError(
                    "Index out of range: " + index);
            
            // Forward to normal call
            try
            {
                return RuntimeShelf.vmStatistic(index);
            }
            catch (MLECallError e)
            {
                throw new SpringMLECallError(e.getMessage(), e);
            }
        }
    },
    
    /** {@link RuntimeShelf#vmType()}. */
    VM_TYPE("vmType:()I")
    {
        /**
         * {@inheritDoc}
         * @since 2020/06/18
         */
        @Override
        public Object handle(SpringThreadWorker __thread, Object... __args)
        {
            return VMType.SPRINGCOAT;
        }
    },
    
    /* End. */
    ;
    
    /** The dispatch key. */
    protected final String key;
    
    /**
     * Initializes the dispatcher info.
     *
     * @param __key The key.
     * @throws NullPointerException On null arguments.
     * @since 2020/06/18
     */
    MLERuntime(String __key)
        throws NullPointerException
    {
        if (__key == null)
            throw new NullPointerException("NARG");
        
        this.key = __key;
    }
    
    /**
     * {@inheritDoc}
     * @since 2020/06/18
     */
    @Override
    public String key()
    {
        return this.key;
    }
}