All Downloads are FREE. Search and download functionalities are using the official Maven repository.

template.ast.ASTNode.tt Maven / Gradle / Ivy

There is a newer version: 2.3.6
Show newest version
# Copyright (c) 2013-2016, The JastAdd Team
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the Lund University nor the names of its
#       contributors may be used to endorse or promote products derived from
#       this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

# This template file contains templates for implicit aspect declarations
# for the ASTNode AST node type

ASTNode.declarations [[
  /**
   * Cached child index. Child indices are assumed to never change (AST should
   * not change after construction).
   * @apilevel internal
   */
  private int $ASTNode.childIndex = -1;

  /** @apilevel low-level */
  public int $ASTNode.getIndexOfChild($ASTNode node) {
    if (node == null) {
      return -1;
    }
$if(RewriteCircularNTA)
    if (node.childIndex >= 0) {
      return node.childIndex;
    }
    for (int i = 0; children != null && i < children.length; i++) {
      if (getChild(i) == node) {
        node.childIndex = i;
        return i;
      }
    }
$else
  $if(LegacyRewrite)
    // Legacy rewrites with rewrite in list can change child position, so update may be needed.
    if (node.childIndex >= 0 && node.childIndex < numChildren && node == children[node.childIndex]) {
  $else
    if (node.childIndex >= 0) {
  $endif
      return node.childIndex;
    }
    for (int i = 0; children != null && i < children.length; i++) {
      if (children[i] == node) {
        node.childIndex = i;
        return i;
      }
    }
$endif
    return -1;
  }

  /** @apilevel internal */
  public static final boolean $ASTNode.generatedWithCacheCycle = $CacheCycle;

$if(!JJTree)
  /** @apilevel low-level */
  protected $ASTNode $ASTNode.parent;

  /** @apilevel low-level */
  protected $ASTNode[] $ASTNode.children;
$endif

$if(TracingEnabled)
  public final $StateClass.Trace $ASTNode.trace() {
    return state().trace();
  }
$endif

$if(Concurrent)
  /** @apilevel internal */
  private static ThreadLocal<$StateClass> $ASTNode.state = new ThreadLocal<$StateClass>() {
    @Override
    public $StateClass initialValue() {
      $StateClass state = new $StateClass();
      threadStates.add(state);
      return state;
    }
  };

  public static java.util.Queue<$StateClass> $ASTNode.threadStates =
      new java.util.concurrent.ConcurrentLinkedQueue<$StateClass>();


  /** @apilevel internal */
  public final static $StateClass $ASTNode.state() {
    return state.get();
  }

  /** @apilevel internal */
  public final static void $ASTNode.resetState() {
    state = new ThreadLocal<$StateClass>() {
      @Override
      public $StateClass initialValue() {
        $StateClass state = new $StateClass();
        threadStates.add(state);
        return state;
      }
    };
  }
$else
  $if(StaticState)
  /** @apilevel internal */
  private static $StateClass $ASTNode.state = new $StateClass();

  /** @apilevel internal */
  public final $StateClass $ASTNode.state() {
    return state;
  }

  /** @apilevel internal */
  public final static $StateClass $ASTNode.resetState() {
    return state = new $StateClass();
  }
  $else
  /** @apilevel internal */
  private $StateClass $ASTNode.state = null;

  /** @apilevel internal */
  public final void $ASTNode.resetState() {
    state = null;
  }

  /** @apilevel internal */
  public final $StateClass $ASTNode.state() {
    if (state == null) {
      if (parent == null) {
        state = new $StateClass();
        #debugASTNodeState
      } else {
        state = parent.state();
      }
    }
    return state;
  }
  $endif
$endif

$if(LegacyRewrite)
  /** @apilevel internal */
  public boolean $ASTNode.in$$Circle = false;

  /** @apilevel internal */
  public boolean $ASTNode.in$$Circle() {
    return in$$Circle;
  }

  /** @apilevel internal */
  public void $ASTNode.in$$Circle(boolean b) {
    in$$Circle = b;
  }
  /** @apilevel internal */
  public boolean $ASTNode.is$$Final = false;

  /** @apilevel internal */
  public boolean $ASTNode.is$$Final() {
    return is$$Final;
  }

  /** @apilevel internal */
  public void $ASTNode.is$$Final(boolean b) {
    is$$Final = b;
  }
$endif

  /**
   * @return an iterator that can be used to iterate over the children of this node.
   * The iterator does not allow removing children.
   */
  public java.util.Iterator $ASTNode.astChildIterator() {
    return new java.util.Iterator() {
      private int index = 0;

      @Override
      public boolean hasNext() {
        return index < getNumChild();
      }

      @Override
      public T next() {
        return hasNext() ? (T) getChild(index++) : null;
      }

      @Override
      public void remove() {
        throw new UnsupportedOperationException();
      }
    };
  }

  /** @return an object that can be used to iterate over the children of this node */
  public Iterable $ASTNode.astChildren() {
    return new Iterable() {
      @Override
      public java.util.Iterator iterator() {
        return astChildIterator();
      }
    };
  }

  $include(ASTNode.nodeToStringMethod)
]]

# Adds debug checks for tree construction.
ASTNode.debugDecls [[
$if(DebugMode)
  /** @apilevel internal */
  protected boolean $ASTNode.debugNodeAttachmentIsRoot() {
    return false;
  }

  /** @apilevel internal */
  private static void $ASTNode.debugNodeAttachment($ASTNode node) {
    if (node == null) {
      throw new RuntimeException("Trying to assign null to a tree child node");
    }

    while (node != null && !node.debugNodeAttachmentIsRoot()) {
$if(LegacyRewrite)
      if (node.in$$Circle()) {
        return;
      }
$endif
      $ASTNode parent = ($ASTNode) node.parent;
      if (parent != null && parent.getIndexOfChild(node) == -1) {
        return;
      }
      node = parent;
    }

    if (node != null) {
      throw new RuntimeException("Trying to insert the same tree at multiple tree locations");
    }
  }
$endif
]]

ASTNode.setParent [[
  /** @apilevel low-level */
  public void $ASTNode.setParent($ASTNode node) {
    $include(ASTNode.incHookSetParent)
    parent = node;
  }
]]

ASTNode.getParent [[
  /** @apilevel low-level */
  public $ASTNode $ASTNode.getParent() {
$if(LegacyRewrite)
    if (parent != null && (($ASTNode) parent).is$$Final() != is$$Final()) {
      state().boundariesCrossed++;
    }
$endif
    $include(ASTNode.incHookGetParent)
    return ($ASTNode) parent;
  }
]]

ASTNode.addChild [[
  /** @apilevel low-level */
  public $ASTNode $ASTNode.addChild(T node) {
    setChild(node, getNumChildNoTransform());
    $include(ASTNode.incHookAddChild)
    return this;
  }
]]

ASTNode.numChildren [[
  /** @apilevel low-level */
   protected int $ASTNode.numChildren;

  /** @apilevel low-level */
  protected int $ASTNode.numChildren() {
    $include(ASTNode.incHookNumChildren)
    return numChildren;
  }

  /** @apilevel low-level */
  public int $ASTNode.getNumChild() {
    return numChildren();
  }

  /**
    * Behaves like getNumChild, but does not invoke AST transformations (rewrites).
    * @apilevel low-level
    */
  public final int $ASTNode.getNumChildNoTransform() {
    return numChildren();
  }
]]

ASTNode.setChild [[
  /** @apilevel low-level */
  public $ASTNode $ASTNode.setChild($ASTNode node, int i) {
$if(DebugMode)
    debugNodeAttachment(node);
$endif
    $include(ASTNode.incHookSetChild1)
    if (children == null) {
      children = new $ASTNode[#initialChildArraySize];
      $include(ASTNode.incHookSetChild2)
    } else if (i >= children.length) {
      $ASTNode c[] = new $ASTNode[i << 1];
      System.arraycopy(children, 0, c, 0, children.length);
      children = c;
      $include(ASTNode.incHookSetChild3)
    }
    $include(ASTNode.incHookSetChild4)
$if(EmptyContainerSingletons)
    if ($include(Opt.isEmpty)) {
      children[i] = $Opt.EMPTY;
    } else if ($include(List.isEmpty)) {
      children[i] = $List.EMPTY;
    } else {
      children[i] = node;
    }
$else
    children[i] = node;
$endif
    if (i >= numChildren) {
      numChildren = i+1;
    }
    if (node != null) {
      node.setParent(this);
      node.childIndex = i;
    }
    $include(ASTNode.incHookSetChild5)
    return this;
  }
]]

ASTNode.insertChild [[
  /** @apilevel low-level */
  public $ASTNode $ASTNode.insertChild($ASTNode node, int i) {
$if(DebugMode)
    debugNodeAttachment(node);
$endif
    $include(ASTNode.incHookInsertChild1)
    if (children == null) {
      children = new $ASTNode[#initialChildArraySize];
      children[i] = node;
      $include(ASTNode.incHookInsertChild2)
    } else {
      $ASTNode c[] = new $ASTNode[children.length + 1];
      System.arraycopy(children, 0, c, 0, i);
      c[i] = node;
      if (i < children.length) {
        System.arraycopy(children, i, c, i+1, children.length-i);
        for(int j = i+1; j < c.length; ++j) {
          if (c[j] != null) {
            c[j].childIndex = j;
          }
        }
      }
      children = c;
      $include(ASTNode.incHookInsertChild3)
    }
    numChildren++;
    if (node != null) {
      node.setParent(this);
      node.childIndex = i;
    }
    return this;
  }
]]

ASTNode.removeChild [[
  /** @apilevel low-level */
  public void $ASTNode.removeChild(int i) {
    if (children != null) {
      $include(ASTNode.incHookRemoveChild1)
      $ASTNode child = ($ASTNode) children[i];
      if (child != null) {
        $include(ASTNode.incHookRemoveChild2)
        child.parent = null;
        child.childIndex = -1;
      }
      // Adding a check of this instance to make sure its a List, a move of children doesn't make
      // any sense for a node unless its a list. Also, there is a problem if a child of a non-List node is removed
      // and siblings are moved one step to the right, with null at the end.
      if (this instanceof $List || this instanceof $Opt) {
        System.arraycopy(children, i+1, children, i, children.length-i-1);
        children[children.length-1] = null;
        numChildren--;
        // fix child indices
        for(int j = i; j < numChildren; ++j) {
          if (children[j] != null) {
            child = ($ASTNode) children[j];
            child.childIndex = j;
          }
        }
      } else {
        children[i] = null;
      }
      $include(ASTNode.incHookRemoveChild3)
    }
  }
]]

ASTNode.getChild [[
  /** @apilevel low-level */
  public T $ASTNode.getChild(int i) {
$if(RewriteEnabled)
 $if(RewriteCircularNTA)
    $ASTNode node = this.getChildNoTransform(i);
    $include(ASTNode.incHookGetChild)
    if (node != null && node.mayHaveRewrite()) {
      $include(ASTNode.incHookGetChildEnterEval)
      $ASTNode rewritten = node.rewrittenNode();
      if (rewritten != node) {
        $include(State.incHookConstructionStart)
        rewritten.setParent(this);
        $include(State.incHookConstructionEnd)
        node = rewritten;
      }
      $include(ASTNode.incHookGetChildExitEval)
    }
    return (T) node;
 $else
    $ASTNode node = this.getChildNoTransform(i);
    if (node == null) {
      return null;
    }
    if (node.is$$Final()) {
      $include(ASTNode.incHookGetChild4)
      $include(ASTNode.incHookGetChild12)
      return (T) node;
    }
    if (!node.mayHaveRewrite()) {
      node.is$$Final(this.is$$Final());
      $include(ASTNode.incHookGetChild4)
      $include(ASTNode.incHookGetChild12)
      return (T) node;
    }
    if (!node.in$$Circle()) {
      $include(ASTNode.traceRewriteEnterCase1)
      $include(ASTNode.incHookGetChild1)
      int rewriteState;
      int _boundaries = state().boundariesCrossed;
      do {
        state().push($StateClass.REWRITE_CHANGE);
        $ASTNode oldNode = node;
        oldNode.in$$Circle(true);
        $include(ASTNode.incHookGetChild5)
        node = node.rewriteTo();
        $include(ASTNode.traceRewriteChange)
        if (node != oldNode) {
          $include(ASTNode.incHookGetChild7)
          this.setChild(node, i);
          $include(ASTNode.incHookGetChild8)
        }
        oldNode.in$$Circle(false);
        rewriteState = state().pop();
        $include(ASTNode.incHookGetChild3)
        $include(ASTNode.incHookGetChild6)
      } while(rewriteState == $StateClass.REWRITE_CHANGE);
      if (rewriteState == $StateClass.REWRITE_NOCHANGE && this.is$$Final()) {
        node.is$$Final(true);
        state().boundariesCrossed = _boundaries;
        $include(ASTNode.traceRewriteCached)
      } else {
        $include(ASTNode.traceRewriteCacheAbort)
      }
      $include(ASTNode.incHookGetChild2)
      $include(ASTNode.traceRewriteExitCase1)
    } else if (this.is$$Final() != node.is$$Final()) {
      state().boundariesCrossed++;
      $include(ASTNode.traceRewriteExitCase2)
    } else {
      $include(ASTNode.traceRewriteExitCase3)
    }
    $include(ASTNode.incHookGetChild11)
    $include(ASTNode.incHookGetChild12)
    return (T) node;
 $endif
$else
    $ASTNode child = getChildNoTransform(i);
    $include(ASTNode.incHookGetChildNT)
    return (T) child;
$endif
  }
]]

ASTNode.getChildNoTransform [[
  /**
    * Gets a child without triggering rewrites.
    * @apilevel low-level
    */
  public T $ASTNode.getChildNoTransform(int i) {
$if(Concurrent)
    return getChildNoTransformBase(i);
  }

  /**
   * Directly accesses the child vector.
   * @apilevel internal
   */
  public T $ASTNode.getChildNoTransformBase(int i) {
$endif
    if (children == null) {
      return null;
    }
    T child = (T) children[i];
    return child;
  }
]]

ASTNode.lineColumnNumbers [[
  /**
   * Line and column information.
   */
  protected int $ASTNode.startLine;
  protected short $ASTNode.startColumn;
  protected int $ASTNode.endLine;
  protected short $ASTNode.endColumn;

  public int $ASTNode.getStartLine() {
    return startLine;
  }
  public short $ASTNode.getStartColumn() {
    return startColumn;
  }
  public int $ASTNode.getEndLine() {
    return endLine;
  }
  public short $ASTNode.getEndColumn() {
    return endColumn;
  }

  public void $ASTNode.setStart(int startLine, short startColumn) {
    this.startLine = startLine;
    this.startColumn = startColumn;
  }
  public void $ASTNode.setEnd(int endLine, short endColumn) {
    this.endLine = endLine;
    this.endColumn = endColumn;
  }
]]




© 2015 - 2024 Weber Informatics LLC | Privacy Policy