package polyglot.ext.jl.ast;

import polyglot.ast.*;
import polyglot.types.*;
import polyglot.visit.*;
import polyglot.util.*;
import java.util.*;

/** 
 * 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;
  }

  /** 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);
    return localInstance(li).type(li.type());
  }

  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);

    w.allowBreak(4, " ");
    w.begin(0);
    w.write("(name " + name + ")");
    w.end();
  }

  public boolean isConstant() {
    return li.isConstant();
  }

  public Object constantValue() {
    return li.constantValue();
  }
}

@@ -43,17 +43,79 @@
 lot.ast.
-*
+Local;%0Aimport polyglot.ast.Node;%0Aimport polyglot.ast.Precedence
 ;%0Aimport
@@ -130,17 +130,23 @@
 t.types.
-*
+Context
 ;%0Aimport
@@ -159,59 +159,302 @@
 lot.
-visit.*;%0Aimport polyglot.util.*;%0Aimport java.util.*
+types.Flags;%0Aimport polyglot.types.LocalInstance;%0Aimport polyglot.types.SemanticException;%0Aimport polyglot.types.TypeSystem;%0Aimport polyglot.util.CodeWriter;%0Aimport polyglot.util.Position;%0Aimport polyglot.visit.PrettyPrinter;%0Aimport polyglot.visit.TypeBuilder;%0Aimport polyglot.visit.TypeChecker
 ;%0A%0A/
@@ -1815,24 +1815,489 @@
 ocal(name);%0A
+    %0A    // if the local is defined in an outer class, then it must be final%0A    if (!c.isLocal(li.name())) %7B%0A        // this local is defined in an outer class%0A        if (!li.flags().isFinal()) %7B%0A            throw new SemanticException(%22Local variable %5C%22%22 + li.name() + %0A                    %22%5C%22 is accessed from an inner class, and must be declared %22 +%0A                    %22final.%22,%0A                    this.position());                     %0A        %7D%0A    %7D%0A    %0A
     return l

Make sure that if a local is defined in an outer class, and used in an inner class, then the local is final.