groovy
  1. groovy
  2. GROOVY-4993

@Memoized AST Transformation for Methods

    Details

    • Type: New Feature New Feature
    • Status: Closed Closed
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.2.0-beta-1
    • Component/s: None
    • Labels:
    • Number of attachments :
      0

      Description

      The whole idea is similar to existing great @Lazy annotation, but it differs in concept: instead of being applied to fields it is applied to methods, thus providing a wider field of use. When applied to getters it serves as an alternative to @Lazy, but applied to other methods it provides what @Lazy can't. Thus it eliminates the need for heavy refactoring in certain situations, by simply letting the user add the annotation to the method.

      Here is a suggestion of how it could work:

      @Cached
      T createX() {
        new T(1, 2, 3)
      }   
      

      gets transformed into:

      private T $createX$result
      T $createX() {
        new T(1, 2, 3)
      }
      T createX() {
        T $result_local = $createX$result
        if ($result_local != null)
          return $result_local
        else {
          synchronized (this) {
            if ($createX$result == null) {
              $createX$result = $createX()
            }
            return $createX$result
          }
        }
      }
      

      This whole thing could be extended to cache different results of a method depending on its arguments, but it's a topic for a discussion.

        Activity

        Hide
        Andrey Bloschetsov added a comment - - edited

        The main points of the implementation:

        • Annotation name is Memoized;
        • Sketch of ASTTransformation implementation:
              public void visit(ASTNode[] nodes, SourceUnit source) {
                  // check params
          
                  AnnotatedNode annNode = (AnnotatedNode) nodes[1];
                  if (annNode instanceof MethodNode) {
                      AnnotationNode ann = (AnnotationNode) nodes[0];
                      if (!MY_TYPE.equals(ann.getClassNode())) {
                          MethodNode methodNode = (MethodNode) annNode;
                          Statement origCode = methodNode.getCode(); // get original code from method
                          Closure<?> closure = null; // TODO create closure with origCode call
                          closure = Memoize.buildMemoizeFunction(new UnlimitedConcurrentCache(), closure); // memoize closure
                          Statement newCode = null; // TODO create statement that call closure and return result
                          methodNode.setCode(newCode);
                      }
                  }
              }
          
        Show
        Andrey Bloschetsov added a comment - - edited The main points of the implementation: Annotation name is Memoized; Sketch of ASTTransformation implementation: public void visit(ASTNode[] nodes, SourceUnit source) { // check params AnnotatedNode annNode = (AnnotatedNode) nodes[1]; if (annNode instanceof MethodNode) { AnnotationNode ann = (AnnotationNode) nodes[0]; if (!MY_TYPE.equals(ann.getClassNode())) { MethodNode methodNode = (MethodNode) annNode; Statement origCode = methodNode.getCode(); // get original code from method Closure<?> closure = null ; // TODO create closure with origCode call closure = Memoize.buildMemoizeFunction( new UnlimitedConcurrentCache(), closure); // memoize closure Statement newCode = null ; // TODO create statement that call closure and return result methodNode.setCode(newCode); } } }
        Hide
        Andrey Bloschetsov added a comment -

        I sent a pull request: https://github.com/groovy/groovy-core/pull/154
        If there are any comments, please let me know.

        Show
        Andrey Bloschetsov added a comment - I sent a pull request: https://github.com/groovy/groovy-core/pull/154 If there are any comments, please let me know.
        Hide
        Andrey Bloschetsov added a comment -

        In the next iteration I could add:

        • Annotation parameters for realization through Closure.memoizeAtLeast, Closure.memoizeAtMost and Closure.memoizeBetween;
        • Handler for abstract methods;
        • Handler for methods that return the void.
        Show
        Andrey Bloschetsov added a comment - In the next iteration I could add: Annotation parameters for realization through Closure.memoizeAtLeast, Closure.memoizeAtMost and Closure.memoizeBetween; Handler for abstract methods; Handler for methods that return the void.
        Hide
        Paul King added a comment -

        Added some comments to the pull request

        Show
        Paul King added a comment - Added some comments to the pull request
        Hide
        Paul King added a comment -

        pull request applied thanks to Andrey Bloschetsov

        Show
        Paul King added a comment - pull request applied thanks to Andrey Bloschetsov

          People

          • Assignee:
            Paul King
            Reporter:
            Nikita Y Volkov
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: