package polyglot.ext.jl.ast;
import java.util.List;
import polyglot.main.*;
import polyglot.ast.*;
import polyglot.types.*;
import polyglot.util.*;
import polyglot.visit.*;
/**
* A <code>Special</code> is an immutable representation of a
* reference to <code>this</code> or <code>super</code in Java. This
* reference can be optionally qualified with a type such as
* <code>Foo.this</code>.
*/
public class Special_c extends Expr_c implements Special
{
protected Special.Kind kind;
protected TypeNode qualifier;
public Special_c(Position pos, Special.Kind kind, TypeNode qualifier) {
super(pos);
this.kind = kind;
this.qualifier = qualifier;
}
/** Get the precedence of the expression. */
public Precedence precedence() {
return Precedence.LITERAL;
}
/** Get the kind of the special expression, either this or super. */
public Special.Kind kind() {
return this.kind;
}
/** Set the kind of the special expression, either this or super. */
public Special kind(Special.Kind kind) {
Special_c n = (Special_c) copy();
n.kind = kind;
return n;
}
/** Get the qualifier of the special expression. */
public TypeNode qualifier() {
return this.qualifier;
}
/** Set the qualifier of the special expression. */
public Special qualifier(TypeNode qualifier) {
Special_c n = (Special_c) copy();
n.qualifier = qualifier;
return n;
}
/** Reconstruct the expression. */
protected Special_c reconstruct(TypeNode qualifier) {
if (qualifier != this.qualifier) {
Special_c n = (Special_c) copy();
n.qualifier = qualifier;
return n;
}
return this;
}
/** Visit the children of the expression. */
public Node visitChildren(NodeVisitor v) {
TypeNode qualifier = (TypeNode) visitChild(this.qualifier, v);
return reconstruct(qualifier);
}
/** Type check the expression. */
public Node typeCheck(TypeChecker tc) throws SemanticException {
TypeSystem ts = tc.typeSystem();
Context c = tc.context();
ClassType t;
if (qualifier == null) {
// an unqualified "this" or "super"
t = c.currentClass();
}
else {
if (! qualifier.type().isClass()) {
throw new SemanticException("Qualified " + kind +
" expression must be of a class type",
qualifier.position());
}
t = qualifier.type().toClass();
if (!c.currentClass().hasEnclosingInstance(t)) {
throw new SemanticException("The nested class \"" +
c.currentClass() + "\" does not have " +
"an enclosing instance of type \"" +
t + "\".", qualifier.position());
}
}
if (c.inStaticContext() && ts.equals(t, c.currentClass())) {
// trying to access "this" or "super" from a static context.
throw new SemanticException("Cannot access a non-static " +
"field or method, or refer to \"this\" or \"super\" " +
"from a static context.", this.position());
}
if (kind == THIS) {
return type(t);
}
else if (kind == SUPER) {
return type(t.superType());
}
return this;
}
/**
* Return the first (sub)term performed when evaluating this
* term.
*/
public Term entry() {
return this;
}
/**
* Visit this term in evaluation order.
*/
public List acceptCFG(CFGBuilder v, List succs) {
return succs;
}
public String toString() {
return (qualifier != null ? qualifier + "." : "") + kind;
}
/** Write the expression to an output file. */
public void prettyPrint(CodeWriter w, PrettyPrinter tr) {
if (qualifier != null) {
print(qualifier, w, tr);
w.write(".");
}
w.write(kind.toString());
}
public void dump(CodeWriter w) {
super.dump(w);
if (kind != null) {
w.allowBreak(4, " ");
w.begin(0);
w.write("(kind " + kind + ")");
w.end();
}
}
}