Class ClassGenerator

java.lang.Object
org.jfuncmachine.compiler.classgen.ClassGenerator

public class ClassGenerator extends Object
Generates classes from ClassDef structures. A single ClassDef structure can result in multiple classes being generated if the class contains any lambdas. This class can write the generated classes to an output directory, return them as an array of GeneratedClass structures containing class names and byte arrays, or it can immediate load the classes and make them available.
  • Field Details

    • options

      public final ClassGeneratorOptions options
      The options used for class generation.
    • currentClass

      public ClassDef currentClass
      The current class being generated.
    • currentMethod

      public MethodDef currentMethod
      The current method being generated.
    • instGen

      public InstructionGenerator instGen
      The class that emits Java instructions for the method.
    • classLoader

      public GeneratedClassLoader classLoader
      A class loader that can be used to immediately load defined classes.
    • newClassDefinitions

      public ClassDef[] newClassDefinitions
      The classes currently being generated. Because the generator sometimes needs to look up classes to check for compatibility between objects or to see if a method has been compiled with tail-call optimization, it may be necessary to examine the definitions of classes that are currently being generated since the class files may not have been generated yet.
  • Constructor Details

    • ClassGenerator

      public ClassGenerator()
      Creates a new class generator using the default options.
    • ClassGenerator

      public ClassGenerator(ClassGeneratorOptions options)
      Creates a new class generator with the specified options.
      Parameters:
      options - An instance of ClassGenerator options.
      See Also:
  • Method Details

    • generate

      public void generate(ClassDef[] classes, String outputDirectory) throws IOException
      Generates all the classes resulting from the given array of ClassDef objects and writes them to the specified directory. Keep in mind that if a ClassDef file contains a lambda expression, it can result in more than one class definition being generated, since lambdas require an interface definition.
      Parameters:
      classes - The class definitions of the classes to be generated.
      outputDirectory - The name of the directory where the .class files should be written.
      Throws:
      IOException - If there is an exception writing the class files
    • generate

      public void generate(ClassDef classDef, String outputDirectory) throws IOException
      Generates all the classes resulting from the given ClassDef object and writes them to the specified directory. Keep in mind that if a ClassDef file contains a lambda expression, it can result in more than one class definition being generated, since lambdas require an interface definition.
      Parameters:
      classDef - The class definition to be generated
      outputDirectory - The name of the directory where the .class files should be written.
      Throws:
      IOException - If there is an exception writing the class files
    • generateClassBytes

      public GeneratedClass[] generateClassBytes(ClassDef[] classDefs)
      Generates all the classes resulting from the given array of ClassDef objects and returns them as an array of GeneratedClass objects which contain the class name and class bytes. Keep in mind that if a class file contains a lambda expression, it can result in more than one class definition being generated, since lambdas require an interface definition.
      Parameters:
      classDefs - The class definitions of the classDefs to be generated.
      Returns:
      An array of GeneratedClass objects containing the class bytes for each class
      See Also:
    • generateClassBytes

      public GeneratedClass[] generateClassBytes(ClassDef classDef)
      Generates all the classes resulting from the given ClassDef object and returns them as an array of GeneratedClass objects which contain the class name and class bytes. Keep in mind that if a ClassDef file contains a lambda expression, it can result in more than one class definition being generated, since lambdas require an interface definition.
      Parameters:
      classDef - The class definition to be generated.
      Returns:
      An array of GeneratedClass objects containing the class bytes for each class
      See Also:
    • generateAndLoad

      public void generateAndLoad(ClassDef[] classDefs)
      Generates all the classes resulting from the given array of ClassDef objects and loads them into the current Java VM. Keep in mind that if a ClassDef file contains a lambda expression, it can result in more than one class definition being generated, since lambdas require an interface definition.
      Parameters:
      classDefs - The class definitions of the classes to be generated.
    • generateAndLoad

      public void generateAndLoad(ClassDef classDef)
      Generates all the classes resulting from the given ClassDef object and loads them into the current Java VM. Keep in mind that if a ClassDef file contains a lambda expression, it can result in more than one class definition being generated, since lambdas require an interface definition.
      Parameters:
      classDef - The class definitions of the classes to be generated.
    • generateAndLoad

      public void generateAndLoad(ClassDef classDef, String outputDirectory) throws IOException
      Generates all the classes resulting from the given ClassDef object and loads them into the current Java VM. Keep in mind that if a ClassDef file contains a lambda expression, it can result in more than one class definition being generated, since lambdas require an interface definition.
      Parameters:
      classDef - The class definitions of the classes to be generated.
      outputDirectory - The name of the directory where the .class files should be written.
      Throws:
      IOException - If there is an exception writing the class files
    • invokeMethod

      public Object invokeMethod(MethodDef methodDef, Object... args)
      Generates a temporary containing class and invokes the method defined by the method def with the given arguments.
      Parameters:
      methodDef - The definition of the method to execute
      args - The method arguments
      Returns:
      The method return value
    • invokeMethod

      public Object invokeMethod(String className, MethodDef methodDef, Object... args)
      Generates a temporary containing class with a specific name and invokes the method defined by the method def with the given arguments.
      Parameters:
      className - The name of the temporary class to generate
      methodDef - The definition of the method to execute
      args - The method arguments
      Returns:
      The method return value
    • invokeMethod

      public Object invokeMethod(ClassDef classDef, String methodName, Object... args)
      Invokes a specific method defined in the given class definition with the given arguments.
      Parameters:
      classDef - The class definition containing the method to execute
      methodName - The name of the method to execute
      args - The method arguments
      Returns:
      The method return value
    • writeClasses

      public void writeClasses(GeneratedClass[] classes, String outputDirectory) throws IOException
      Writes an array of generated class files to the specified output directory.
      Parameters:
      classes - The classes to write
      outputDirectory - The destination output directory
      Throws:
      IOException - If there is an exception writing the class files
    • generateLambdaInterface

      public GeneratedClass generateLambdaInterface(LambdaIntInfo info)
      Generates the bytecode for a lambda interface.
      Parameters:
      info - A descriptor for the lambda interface and its single method
      Returns:
      A GeneratedClass containing the bytecode and the class name
    • addMethodToGenerate

      public void addMethodToGenerate(MethodDef method)
      Add a method that needs to be generated. This is usually done by the method generation when there is a lambda
      Parameters:
      method - The method to be genrated
    • addLocalVariable

      public void addLocalVariable(org.objectweb.asm.tree.LocalVariableNode node)
      Adds a definition of a local variable that is being used by the current method.
      Parameters:
      node - A node describing the local variable
    • addTryCatch

      public void addTryCatch(org.objectweb.asm.tree.TryCatchBlockNode node)
      Adds a try-catch block definition that is being generated by the current method.
      Parameters:
      node - A node describing a try-catch block
    • allocateLambdaInt

      public LambdaIntInfo allocateLambdaInt(FunctionType functionType)
      Allocates a lambda interface name for the given function type and saves it in a map of interfaces.
      Parameters:
      functionType - The type of the single method in the interface
      Returns:
      A descriptor describing the interface
    • allocateLambda

      public LambdaInfo allocateLambda(FunctionType type)
      Allocates a new lambda interface with a unique name.
      Parameters:
      type - The type of the lambda method
      Returns:
      A descriptor describing the lambda
    • className

      public String className(ClassDef classDef)
      Converts a dot-separated class name into a slash-separated one
      Parameters:
      classDef - The class definition containing the package name and class name
      Returns:
      A slash-separated class name
    • className

      public String className(String packageName, String name)
      Converts a dot-separated class name into a slash-separated one
      Parameters:
      packageName - The package name of the class
      name - The name of the class
      Returns:
      A slash-separated class name
    • className

      public String className(String name)
      Converts a dot-separated class name into a slash-separated one
      Parameters:
      name - A class name presumably containing both a package and class name
      Returns:
      A slash-separated class name
    • classSignature

      public String classSignature(ClassDef classDef)
      Returns a class signature name for a class (L + class signature + ;)
      Parameters:
      classDef - The class definition to get the signature name for
      Returns:
      The signature of the class
    • methodDescriptor

      public String methodDescriptor(MethodDef methodDef)
      Creates a method descriptor for the given method definition. The descriptor encodes the types of the method parameters as well as the return type as per the JVM spec. For example: A method that takes a string and an integer as parameters and returns void would be encoded as: (Ljava/lang/String;I)V
      Parameters:
      methodDef - The definition of the method to generate the descriptor for
      Returns:
      A string descriptor encoding the types according to the JVM spec
    • lambdaReturnDescriptor

      public String lambdaReturnDescriptor(MethodDef methodDef, String lambdaInterfaceName)
      Generates a method descritor for a method that returns a lambda.
      Parameters:
      methodDef - The definition of the method
      lambdaInterfaceName - The type of interface being returned
      Returns:
      A string descriptor of the method according to the JVM spec
    • methodDescriptor

      public String methodDescriptor(Expression[] arguments, Type returnType)
      Creates a method descriptor from an array of expressions that represent the method parameters, and the method's return type.
      Parameters:
      arguments - An array of expressions that represent the methods parameters
      returnType - The return type of the method
      Returns:
      A string descriptor of the method according to the JVM spec
    • methodDescriptor

      public String methodDescriptor(Type[] parameterTypes, Type returnType)
      Creates a method descriptor from the given parameter types and return type.
      Parameters:
      parameterTypes - An array describing the types of the method's parameters
      returnType - The return type of the method
      Returns:
      A string descriptor of the method according to the JVM spec
    • lambdaInDyDescriptor

      public String lambdaInDyDescriptor(Type[] parameterTypes, String className)
      Creates a method descriptor specifically used to describe a lambda to the invokesynamic instruction.
      Parameters:
      parameterTypes - The types of the method's parameters
      className - The class name of the lambda's interface
      Returns:
      A string descriptor of the lambda according to the JVM spec
    • lambdaMethodDescriptor

      public String lambdaMethodDescriptor(Type[] capturedParameterTypes, Type[] parameterTypes, Type returnType)
      Returns a descriptor of a lambda's method type, which includes the lambda's declared parameters as well as any local variables captured by the lambda.
      Parameters:
      capturedParameterTypes - The types of the variables captured by the lambda
      parameterTypes - The types of the methods declared parameters
      returnType - The return type of the lambda
      Returns:
      A string descriptor of the lambda according to the JVM spec
    • getTypeDescriptor

      public String getTypeDescriptor(Type type)
      Return a JVM type descriptor for a given type. This is done here instead of inside the Type interface in order to handle the FunctionType correctly.
      Parameters:
      type - The type to return the descriptor for
      Returns:
      A JVM type descriptor for the given type
    • getLoadedClass

      public Class getLoadedClass(String className)
      Returns a class previously loaded by the internal classloader.
      Parameters:
      className - The fully-qualified name of the class to return
      Returns:
      The class if it was loaded, or null if there is no class with that name