Class ELCompiler

java.lang.Object
io.micronaut.el.processor.compiler.ELCompiler

@Internal public final class ELCompiler extends Object
The compiler lowering the abstract syntax tree of an expression to the source model of Micronaut SourceGen.

Every construct of the language is compiled to the equivalent Java expression. The property accesses, the method invocations, the static references and the functions whose types are known at compilation time are compiled to direct invocations, the remaining ones are compiled to the resolution described in the sections 1.5 and 1.6 of the specification. The operators whose operand types are known at compilation time are compiled to the Java operators the runtime would reach, see inlineBinary(BinaryOperator, Typed, Typed).

Since:
1.0
Author:
Denis Stepanov
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static final record 
    The base object and the property of an lvalue.
    static final record 
    A compiled expression with the type known at compilation time, when there is one.
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    io.micronaut.sourcegen.model.ExpressionDef
    compile(ELNode node, io.micronaut.sourcegen.model.ExpressionDef elContext)
    Compiles an expression.
    io.micronaut.sourcegen.model.StatementDef
    compileEvaluation(ELNode node, io.micronaut.sourcegen.model.ExpressionDef elContext, Function<io.micronaut.sourcegen.model.ExpressionDef, ELCompiler.Typed> body)
    Compiles the evaluation of an expression as the body of a method returning its result.
    compileLValue(ELNode node, io.micronaut.sourcegen.model.ExpressionDef elContext)
    Compiles the base object and the property of an lvalue, as described in the section 1.13 of the specification.
    compileTyped(ELNode node, io.micronaut.sourcegen.model.ExpressionDef ctx)
    Compiles an expression, with its static type.
    boolean
    evaluatesTo(io.micronaut.inject.ast.ClassElement expected)
     
    @Nullable io.micronaut.inject.ast.ClassElement
     
    static boolean
     
    io.micronaut.inject.ast.ClassElement
    The expected type inferred for an expression whose declaration omits it: the static type of the result, a primitive as the wrapper the evaluation returns, Object when the compiler does not know the type.
    io.micronaut.inject.ast.ClassElement
    The static type of an expression, for the return type of a method expression whose declaration omits it.
    io.micronaut.sourcegen.model.ExpressionDef
    invokeRuntime(io.micronaut.sourcegen.model.ClassTypeDef owner, String name, io.micronaut.sourcegen.model.TypeDef returning, io.micronaut.sourcegen.model.ExpressionDef... values)
    Invokes a static method of the runtime with the signature the runtime actually declares, for the writers.
     

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • ELCompiler

      public ELCompiler(CompilationContext context)
      Parameters:
      context - The compilation context
  • Method Details

    • compile

      public io.micronaut.sourcegen.model.ExpressionDef compile(ELNode node, io.micronaut.sourcegen.model.ExpressionDef elContext)
      Compiles an expression.
      Parameters:
      node - The parsed expression
      elContext - The expression holding the jakarta.el.ELContext
      Returns:
      The compiled expression
    • compileEvaluation

      public io.micronaut.sourcegen.model.StatementDef compileEvaluation(ELNode node, io.micronaut.sourcegen.model.ExpressionDef elContext, Function<io.micronaut.sourcegen.model.ExpressionDef, ELCompiler.Typed> body)
      Compiles the evaluation of an expression as the body of a method returning its result.

      An identifier the expression resolves more than once is resolved once, into a local the references share, when nothing in the expression can change what the identifier denotes during the evaluation: the section 1.5.1 of the specification resolves an identifier through the lambda arguments, the variable mapper and the resolvers, and only the assignment and the semicolon operators can alter any of these within one evaluation. The bodies of the lambda expressions keep resolving through their own context.

      When the expression holds a lambda expression, the context is first bound to a local: a Java lambda compiled from it captures the context, and the Java source writer of SourceGen 2.1.0 cannot render a captured method parameter, while its bytecode writer captures a local.

      Parameters:
      node - The parsed expression
      elContext - The expression holding the jakarta.el.ELContext
      body - The compilation of the result with the context to use, once the shared identifiers are in place
      Returns:
      The body of the method
    • evaluationType

      public @Nullable io.micronaut.inject.ast.ClassElement evaluationType()
      Returns:
      The static type of the result of the last compileEvaluation(ELNode, ExpressionDef, Function), or null when it is not known
    • inferredEvaluationType

      public io.micronaut.inject.ast.ClassElement inferredEvaluationType()
      The expected type inferred for an expression whose declaration omits it: the static type of the result, a primitive as the wrapper the evaluation returns, Object when the compiler does not know the type.
      Returns:
      The inferred type
    • inferredType

      public io.micronaut.inject.ast.ClassElement inferredType(ELNode node)
      The static type of an expression, for the return type of a method expression whose declaration omits it.
      Parameters:
      node - The parsed expression
      Returns:
      The inferred type
    • evaluatesTo

      public boolean evaluatesTo(io.micronaut.inject.ast.ClassElement expected)
      Parameters:
      expected - The expected type of a value expression
      Returns:
      Whether the result of the last compileEvaluation(ELNode, ExpressionDef, Function) is known to be of the expected type, so that the coercion of the section 1.23 of the specification is the identity
    • compileLValue

      public @Nullable ELCompiler.LValue compileLValue(ELNode node, io.micronaut.sourcegen.model.ExpressionDef elContext)
      Compiles the base object and the property of an lvalue, as described in the section 1.13 of the specification.
      Parameters:
      node - The parsed expression
      elContext - The expression holding the jakarta.el.ELContext
      Returns:
      The lvalue or null when the expression is not an lvalue
    • invokeRuntime

      public io.micronaut.sourcegen.model.ExpressionDef invokeRuntime(io.micronaut.sourcegen.model.ClassTypeDef owner, String name, io.micronaut.sourcegen.model.TypeDef returning, io.micronaut.sourcegen.model.ExpressionDef... values)
      Invokes a static method of the runtime with the signature the runtime actually declares, for the writers.
      Parameters:
      owner - The declaring type
      name - The method name
      returning - The type the result is used as
      values - The arguments
      Returns:
      The invocation
      See Also:
      • runtime(ClassTypeDef, String, TypeDef, ExpressionDef...)
    • compileTyped

      public ELCompiler.Typed compileTyped(ELNode node, io.micronaut.sourcegen.model.ExpressionDef ctx)
      Compiles an expression, with its static type.
      Parameters:
      node - The parsed expression
      ctx - The expression holding the jakarta.el.ELContext
      Returns:
      The compiled expression and its type
    • unresolvedIdentifiers

      public Set<String> unresolvedIdentifiers()
      Returns:
      The identifiers the compiled code resolves dynamically because nothing declares them: not a variable, not a lambda parameter, not an import
    • hasAssignments

      public static boolean hasAssignments(ELNode node)
      Parameters:
      node - A parsed expression
      Returns:
      Whether the expression assigns or sequences, which makes what an identifier denotes dynamic