template.ast.State.tt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jastadd Show documentation
Show all versions of jastadd Show documentation
A metacompilation framework for Java using attribute grammars.
# 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.
ASTNode$State = [[
/** @apilevel internal */
public class $StateClass {
/** @apilevel internal */
protected static class CircularValue {
Object value;
Cycle cycle;
}
/**
* Instances of this class are used to uniquely identify circular evaluation cycles.
* @apilevel internal
*/
protected static class Cycle {
}
/** The cycle ID used outside of circular evaluation. */
public static final Cycle NON_CYCLE = new Cycle();
/**
* Tracks the state of the current circular evaluation. This class defines a
* stack structure where the next element on the stack is pointed to by the
* {@code next} field.
* @apilevel internal
*/
protected static class CircleState {
final CircleState next;
boolean inCircle = false;
$if(LegacyRewrite)
boolean resetCycle = false;
$endif
boolean change = false;
/** Evaluation depth of lazy attributes. */
int lazyAttribute = 0;
$if(CacheCycle)
boolean lastCycle = false;
$endif
$if(ComponentCheck)
boolean completed = false; // Whether the circular evaluation has completed.
$endif
/** Cycle ID of the latest cycle in this circular evaluation. */
Cycle cycle = NON_CYCLE;
protected CircleState(CircleState next) {
this.next = next;
}
}
/** Sentinel circle state representing non-circular evaluation. */
private static final CircleState CIRCLE_BOTTOM = new CircleState(null);
/**
* Current circular state.
* @apilevel internal
*/
private CircleState circle = CIRCLE_BOTTOM;
/** @apilevel internal */
protected boolean inCircle() {
return circle.inCircle;
}
/** @apilevel internal */
protected boolean calledByLazyAttribute() {
return circle.lazyAttribute > 0;
}
/** @apilevel internal */
protected void enterLazyAttribute() {
circle.lazyAttribute += 1;
}
/** @apilevel internal */
protected void leaveLazyAttribute() {
circle.lazyAttribute -= 1;
}
/** @apilevel internal */
protected void enterCircle() {
CircleState next = new CircleState(circle);
next.inCircle = true;
circle = next;
}
/** @apilevel internal */
protected void leaveCircle() {
$if(ComponentCheck)
circle.completed = true;
$endif
circle = circle.next;
}
/** @apilevel internal */
protected Cycle nextCycle() {
Cycle cycle = new Cycle();
circle.cycle = cycle;
return cycle;
}
/** @apilevel internal */
protected Cycle cycle() {
return circle.cycle;
}
/** @apilevel internal */
protected CircleState currentCircle() {
return circle;
}
$if(ComponentCheck)
/**
* Throws a RuntimeException if called on a different circular evaluation
* than the given circle state.
* @apilevel internal
*/
protected void assertSameCircle(CircleState prev, String attribute) {
if (prev != null && !prev.completed && prev != currentCircle()) {
throw new RuntimeException(String.format("Circular definition of attribute %s.", attribute));
}
}
$endif
/** @apilevel internal */
protected void setChangeInCycle() {
circle.change = true;
}
/** @apilevel internal */
protected boolean testAndClearChangeInCycle() {
boolean change = circle.change;
circle.change = false;
return change;
}
/** @apilevel internal */
protected boolean changeInCycle() {
return circle.change;
}
$if(CacheCycle)
/** @apilevel internal */
protected boolean lastCycle() {
return circle.lastCycle;
}
/** @apilevel internal */
protected void startLastCycle() {
circle.lastCycle = true;
}
$endif
$if(LegacyRewrite)
/** @apilevel internal */
protected void startResetCycle() {
circle.resetCycle = true;
}
/** @apilevel internal */
protected boolean resetCycle() {
return circle.resetCycle;
}
$endif
protected $StateClass() {
$if(ComponentCheck)
circle.completed = true;
$endif
$if(LegacyRewrite)
stack = new int[64];
pos = 0;
$endif
}
$if(LegacyRewrite)
/** @apilevel internal */
public static final int REWRITE_CHANGE = 1;
/** @apilevel internal */
public static final int REWRITE_NOCHANGE = 2;
/** @apilevel internal */
public static final int REWRITE_INTERRUPT = 3;
public int boundariesCrossed = 0;
// state code
private int[] stack;
private int pos;
private void ensureSize(int size) {
if (size < stack.length) {
return;
}
int[] newStack = new int[stack.length * 2];
System.arraycopy(stack, 0, newStack, 0, stack.length);
stack = newStack;
}
public void push(int i) {
ensureSize(pos+1);
stack[pos++] = i;
}
public int pop() {
return stack[--pos];
}
public int peek() {
return stack[pos - 1];
}
$endif
$include(State.incHook)
$if(TracingEnabled)
private Trace trace = null;
public Trace trace() {
if (trace == null) {
trace = new Trace();
}
return trace;
}
$include(TraceClass)
$endif
}
]]
ASTNode$State.reset [[
/** @apilevel internal */
public void $StateClass.reset() {
$SynchBegin
// Reset circular evaluation state.
circle = CIRCLE_BOTTOM;
$if(LegacyRewrite)
boundariesCrossed = 0;
$endif
$SynchEnd
}
]]