package polyglot.ext.jl.ast; import polyglot.ast.Local; import polyglot.ast.Node; import polyglot.ast.Term; import polyglot.ast.Precedence; import polyglot.types.Context; import polyglot.types.Flags; import polyglot.types.LocalInstance; import polyglot.types.SemanticException; import polyglot.types.TypeSystem; import polyglot.util.CodeWriter; import polyglot.util.Position; import polyglot.visit.PrettyPrinter; import polyglot.visit.TypeBuilder; import polyglot.visit.TypeChecker; import polyglot.visit.CFGBuilder; import java.util.List; /** * A local variable expression. */ public class Local_c extends Expr_c implements Local { protected String name; protected LocalInstance li; public Local_c(Position pos, String name) { super(pos); this.name = name; } /** Get the precedence of the local. */ public Precedence precedence() { return Precedence.LITERAL; } /** Get the name of the local. */ public String name() { return this.name; } /** Set the name of the local. */ public Local name(String name) { Local_c n = (Local_c) copy(); n.name = name; return n; } /** Return the access flags of the variable. */ public Flags flags() { return li.flags(); } /** Get the local instance of the local. */ public LocalInstance localInstance() { return li; } /** Set the local instance of the local. */ public Local localInstance(LocalInstance li) { Local_c n = (Local_c) copy(); n.li = li; return n; } public Node buildTypes(TypeBuilder tb) throws SemanticException { Local_c n = (Local_c) super.buildTypes(tb); TypeSystem ts = tb.typeSystem(); LocalInstance li = ts.localInstance(position(), Flags.NONE, ts.unknownType(position()), name); return n.localInstance(li); } /** Type check the local. */ public Node typeCheck(TypeChecker tc) throws SemanticException { Context c = tc.context(); LocalInstance li = c.findLocal(name); // if the local is defined in an outer class, then it must be final if (!c.isLocal(li.name())) { // this local is defined in an outer class if (!li.flags().isFinal()) { throw new SemanticException("Local variable \"" + li.name() + "\" is accessed from an inner class, and must be declared " + "final.", this.position()); } } return localInstance(li).type(li.type()); } /** * 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 name; } /** Write the local to an output file. */ public void prettyPrint(CodeWriter w, PrettyPrinter tr) { w.write(name); } /** Dumps the AST. */ public void dump(CodeWriter w) { super.dump(w); if (li != null) { w.allowBreak(4, " "); w.begin(0); w.write("(instance " + li + ")"); w.end(); } w.allowBreak(4, " "); w.begin(0); w.write("(name " + name + ")"); w.end(); } public boolean isConstant() { return li.isConstant(); } public Object constantValue() { return li.constantValue(); } }