Package st.gravel.support.jvm.runtime

Source Code of st.gravel.support.jvm.runtime.JavaSystemMappingCompilerTools$CompiledClass

package st.gravel.support.jvm.runtime;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;

import st.gravel.core.Symbol;
import st.gravel.support.compiler.ASMClassWriter;
import st.gravel.support.compiler.ast.AbsoluteReference;
import st.gravel.support.compiler.ast.ClassMapping;
import st.gravel.support.compiler.ast.Reference;
import st.gravel.support.compiler.ast.SystemMapping;
import st.gravel.support.compiler.ast.SystemMappingCompilerTools;
import st.gravel.support.compiler.jvm.Invoke;
import st.gravel.support.compiler.jvm.Invoke.Invoke_Factory;
import st.gravel.support.compiler.jvm.InvokeInterface;
import st.gravel.support.compiler.jvm.InvokeStatic;
import st.gravel.support.compiler.jvm.InvokeStatic.InvokeStatic_Factory;
import st.gravel.support.compiler.jvm.InvokeVirtual;
import st.gravel.support.compiler.jvm.JVMArrayType;
import st.gravel.support.compiler.jvm.JVMBooleanType;
import st.gravel.support.compiler.jvm.JVMByteType;
import st.gravel.support.compiler.jvm.JVMCharType;
import st.gravel.support.compiler.jvm.JVMClass;
import st.gravel.support.compiler.jvm.JVMDefinedObjectType;
import st.gravel.support.compiler.jvm.JVMDoubleType;
import st.gravel.support.compiler.jvm.JVMFloatType;
import st.gravel.support.compiler.jvm.JVMIntType;
import st.gravel.support.compiler.jvm.JVMLongType;
import st.gravel.support.compiler.jvm.JVMMethodType;
import st.gravel.support.compiler.jvm.JVMType;
import st.gravel.support.compiler.jvm.JVMVoidType;
import st.gravel.support.jvm.ArrayExtensions;
import st.gravel.support.jvm.Block0;
import st.gravel.support.jvm.Block1;
import st.gravel.support.jvm.Block2;
import st.gravel.support.jvm.ObjectClass;

public final class JavaSystemMappingCompilerTools extends
    SystemMappingCompilerTools {

  private int classCounter = 1;
  private int nlrMarkers = 1;

  private static class CompiledClass {

    private final JVMClass jvmClass;
    private final Class<?> javaClass;

    public CompiledClass(JVMClass jvmClass, Class<?> javaClass) {
      this.jvmClass = jvmClass;
      this.javaClass = javaClass;
    }

  }

  private final HashMap<JVMDefinedObjectType, CompiledClass> jvmClasses = new HashMap<>();

  public MethodHandle bindMethodHandle_to_(MethodHandle _methodHandle,
      Object _object) {
    return _methodHandle.bindTo(_object);
  }

  @Override
  public Invoke createInvokeInstruction_name_numArgs_(
      JVMDefinedObjectType _type, String _name, int _numArgs) {
    Class<?> receiverClass;
    try {
      receiverClass = Class.forName(_type.dottedClassName());
    } catch (ClassNotFoundException e) {
      return null;
    }
    Method method = MethodTools.searchForStaticMethod(receiverClass, _name, _numArgs);
    if (method == null) {
      method = MethodTools.searchForStaticMethod(receiverClass, _name, _numArgs + 1);
    }
    if (method == null) {
      method = MethodTools.searchForMethod(receiverClass, _name, _numArgs, false);

      if (method == null) {
        return null;
      }
      if (receiverClass.isInterface()) {
        return createInvoke(InvokeInterface.factory, _type, _name, method);
      } else {
        return createInvoke(InvokeVirtual.factory, _type, _name, method);
      }

    } else {
      return createInvoke(InvokeStatic.factory, _type, _name, method);
    }
  }

  private Invoke createInvoke(Invoke_Factory invokeFactory,
      JVMDefinedObjectType _type, String _name, Method method) {
    JVMType[] arguments = ArrayExtensions.collect_(
        method.getParameterTypes(),
        new Block1<JVMType, Class<?>>() {

          @Override
          public JVMType value_(Class<?> arg1) {
            return jvmTypeForClass_(arg1);
          }
        });
    JVMMethodType _aJVMMethodType = JVMMethodType.factory
        .returnType_arguments_(
            jvmTypeForClass_(method.getReturnType()), arguments);
    return invokeFactory.ownerType_name_signature_(_type, _name,
        _aJVMMethodType);
  }

  @Override
  public Object createSingletonForClass_(Class _aJavaClass) {
    try {
      return _aJavaClass.getConstructor().newInstance();
    } catch (InstantiationException | IllegalAccessException
        | IllegalArgumentException | InvocationTargetException
        | NoSuchMethodException | SecurityException e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public Object evaluateBlock0Class_(Class _aClass) {
    try {
      Object function = _aClass.getConstructor().newInstance();
      Object value = _aClass.getMethod("value").invoke(function);
      return value;
    } catch (InstantiationException | IllegalAccessException
        | IllegalArgumentException | InvocationTargetException
        | NoSuchMethodException | SecurityException e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public Class findJavaClass_(Symbol[] path) {
    if ((path.length == 1) && (path[0].asString().equals("byte[]"))) return byte[].class;
    try {
      return Class
          .forName(referenceAsClassName_(AbsoluteReference.factory
              .path_(path)));
    } catch (ClassNotFoundException e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public SystemMappingCompilerTools initializeClass_systemMapping_(
      ClassMapping _aClassMapping, SystemMapping aSystemMapping) {

    Class identityClass = _aClassMapping.identityClass();

    if (identityClass == null)
      return this;
    try {

      Method method = identityClass.getDeclaredMethod("initialize");
      Object instance = aSystemMapping
          .singletonAtReference_(_aClassMapping.reference().nonmeta());
      final MethodHandle unreflect = MethodHandles.lookup().unreflect(
          method);
      System.out.println("Initializing " + identityClass);
      unreflect.invoke(instance);
      return this;
    } catch (NoSuchMethodException e) {
      return this;
    } catch (SecurityException | IllegalAccessException
        | IllegalArgumentException | InvocationTargetException e) {
      throw new RuntimeException(e);
    } catch (Throwable e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public boolean isAssignable_from_(Class _aClass, Class _bClass) {
    return _aClass != null && _bClass != null
        && _aClass.isAssignableFrom(_bClass);
  }

  @Override
  public JVMClass jvmClassForType_ifAbsent_(
      JVMDefinedObjectType _aJVMDefinedObjectType,
      Block0<JVMClass> _aBlock) {
    return jvmClasses.get(_aJVMDefinedObjectType).jvmClass;
  }

  @Override
  public JVMType jvmTypeForClass_(Class _aClass) {
    if (_aClass.isPrimitive()) {
      if (_aClass == void.class)
        return JVMVoidType.factory.basicNew();
      if (_aClass == char.class)
        return JVMCharType.factory.basicNew();
      if (_aClass == byte.class)
        return JVMByteType.factory.basicNew();
      if (_aClass == int.class)
        return JVMIntType.factory.basicNew();
      if (_aClass == long.class)
        return JVMLongType.factory.basicNew();
      if (_aClass == boolean.class)
        return JVMBooleanType.factory.basicNew();
      if (_aClass == float.class)
        return JVMFloatType.factory.basicNew();
      if (_aClass == double.class)
        return JVMDoubleType.factory.basicNew();
      throw new RuntimeException("niy: " + _aClass);
    }
    if (_aClass.isArray()) {
      return JVMArrayType.factory.elementType_(this
          .jvmTypeForClass_(_aClass.getComponentType()));
    }
    return JVMDefinedObjectType.factory.dottedClassName_(_aClass
        .getCanonicalName());
  }

  @Override
  public MethodHandle methodHandleAt_numArgs_in_identityClass_isStatic_(
      String methodName, int baseNumArgs, Class javaClass,
      Class _identityClass, boolean isStatic) {
    int numArgs = baseNumArgs + (isStatic ? 1 : 0);
    Method method = MethodTools.searchForMethod(javaClass, methodName,
        numArgs, isStatic);
    if (method == null) {
      throw new RuntimeException("Method not found: " + methodName
          + " in: " + javaClass);
    }
    try {
      if (isStatic) {
        return MethodHandles
            .lookup()
            .in(javaClass)
            .findStatic(javaClass, methodName,
                MethodTools.asMethodType(method));
      } else {
        return MethodHandles
            .lookup()
            .in(javaClass)
            .findVirtual(javaClass, methodName,
                MethodTools.asMethodType(method));
      }
    } catch (NoSuchMethodException | IllegalAccessException e) {
      return null;
    }
  }

  @Override
  public SystemMappingCompilerTools methodNamesIn_do_(Class javaClass,
      Block2<Object, String, Integer> block) {
    for (Method m : javaClass.getMethods()) {
      if (!Modifier.isStatic(m.getModifiers())
          && m.getDeclaringClass() == javaClass)
        block.value_value_(m.getName(), m.getParameterTypes().length);
    }
    return this;
  }

  @Override
  public AlmostFinalValue newSingletonHolder_value_(
      AbsoluteReference _reference, Object _value) {
    AlmostFinalValue almostFinalValue = new AlmostFinalValue();
    almostFinalValue.setValue(_value);
    return almostFinalValue;
  }

  @Override
  public AlmostFinalValue newSingletonHolder_initializer_(
      final AbsoluteReference _reference, final Block0<Object> block) {
    AlmostFinalValue almostFinalValue = new AlmostFinalValue() {

      @Override
      protected Object initialValue() {
        return block.value();
      }
     
    };
    return almostFinalValue;
  }

  @Override
  public String nextExtensionPostfix() {
    return "Extension" + classCounter++;
  }

  @Override
  public String nextNlrMarker() {
    return "__NonLocalReturn" + nlrMarkers++;
  }

  @Override
  public String referenceAsClassName_(Reference reference) {
    if (reference.isMeta()) {
      return reference.nonmeta().toString() + "$Factory";
    }
    return reference.toString();
  }

  @Override
  public SystemMappingCompilerTools resetCallsites() {
    BaseCallSite.resetAll();
    return this;
  }

  @Override
  public Object valueOfSingletonHolder_(AlmostFinalValue _holder) {
    try {
      return _holder.createGetter().invokeExact();
    } catch (Throwable e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public Class writeClass_(JVMClass jvmClass) {
    JVMDefinedObjectType key = jvmClass.type();
    CompiledClass current = jvmClasses.get(key);
    if (current == null) {
      current = new CompiledClass(jvmClass,
          new ASMClassWriter(jvmClass).createClass());
      jvmClasses.put(key, current);
    }
    return current.javaClass;
  }

  @Override
  public SystemMappingCompilerTools runAstInit_(JVMClass jvmClass) {
    JVMDefinedObjectType key = jvmClass.type();
    CompiledClass current = jvmClasses.get(key);

    Object[] astConstants = jvmClass.astConstants();
    if (astConstants.length == 0)
      return this;
    MethodType type = MethodType.genericMethodType(astConstants.length)
        .changeReturnType(void.class);
    MethodHandle findStatic;
    try {
      findStatic = MethodHandles.lookup().findStatic(current.javaClass,
          "_astinit", type);
      findStatic.invokeWithArguments(astConstants);
    } catch (Throwable e) {
      throw new RuntimeException(e);
    }
    return this;
  }

  @Override
  public Class classForName_(String _aString) {
    CompiledClass compiledClass = jvmClasses.get(JVMDefinedObjectType.factory.dottedClassName_(_aString));
    if (compiledClass != null) return compiledClass.javaClass;
    throw new RuntimeException("niy");
  }
}
TOP

Related Classes of st.gravel.support.jvm.runtime.JavaSystemMappingCompilerTools$CompiledClass

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.