package polyglot.ext.jl.ast;
import polyglot.ast.*;
import polyglot.types.*;
import polyglot.visit.*;
import polyglot.util.*;
import polyglot.frontend.Source;
import polyglot.types.Package;
import java.util.*;
/**
* A <code>SourceFile</code> is an immutable representations of a Java
* langauge source file. It consists of a package name, a list of
* <code>Import</code>s, and a list of <code>GlobalDecl</code>s.
*/
public class SourceFile_c extends Node_c implements SourceFile
{
protected PackageNode package_;
protected List imports;
protected List decls;
protected ImportTable importTable;
protected Source source;
public SourceFile_c(Position pos, PackageNode package_, List imports, List decls) {
super(pos);
this.package_ = package_;
this.imports = TypedList.copyAndCheck(imports, Import.class, true);
this.decls = TypedList.copyAndCheck(decls, TopLevelDecl.class, true);
}
/** Get the source of the source file. */
public Source source() {
return this.source;
}
/** Set the source of the source file. */
public SourceFile source(Source source) {
SourceFile_c n = (SourceFile_c) copy();
n.source = source;
return n;
}
/** Get the package of the source file. */
public PackageNode package_() {
return this.package_;
}
/** Set the package of the source file. */
public SourceFile package_(PackageNode package_) {
SourceFile_c n = (SourceFile_c) copy();
n.package_ = package_;
return n;
}
/** Get the imports of the source file. */
public List imports() {
return Collections.unmodifiableList(this.imports);
}
/** Set the imports of the source file. */
public SourceFile imports(List imports) {
SourceFile_c n = (SourceFile_c) copy();
n.imports = TypedList.copyAndCheck(imports, Import.class, true);
return n;
}
/** Get the declarations of the source file. */
public List decls() {
return Collections.unmodifiableList(this.decls);
}
/** Set the declarations of the source file. */
public SourceFile decls(List decls) {
SourceFile_c n = (SourceFile_c) copy();
n.decls = TypedList.copyAndCheck(decls, TopLevelDecl.class, true);
return n;
}
/** Get the declarations of the source file. */
public ImportTable importTable() {
return this.importTable;
}
/** Set the declarations of the source file. */
public SourceFile importTable(ImportTable importTable) {
SourceFile_c n = (SourceFile_c) copy();
n.importTable = importTable;
return n;
}
/** Reconstruct the source file. */
protected SourceFile_c reconstruct(PackageNode package_, List imports, List decls) {
if (package_ != this.package_ || ! CollectionUtil.equals(imports, this.imports) || ! CollectionUtil.equals(decls, this.decls)) {
SourceFile_c n = (SourceFile_c) copy();
n.package_ = package_;
n.imports = TypedList.copyAndCheck(imports, Import.class, true);
n.decls = TypedList.copyAndCheck(decls, TopLevelDecl.class, true);
return n;
}
return this;
}
/** Visit the children of the source file. */
public Node visitChildren(NodeVisitor v) {
PackageNode package_ = (PackageNode) visitChild(this.package_, v);
List imports = visitList(this.imports, v);
List decls = visitList(this.decls, v);
return reconstruct(package_, imports, decls);
}
/**
* Build type objects for the source file. Set the visitor's import table
* field before we recurse into the declarations.
*/
public NodeVisitor buildTypesEnter(TypeBuilder tb) throws SemanticException {
TypeSystem ts = tb.typeSystem();
ImportTable it;
if (package_ != null) {
it = ts.importTable(source.name(), package_.package_());
}
else {
it = ts.importTable(source.name(), null);
}
tb.setImportTable(it);
return tb;
}
/**
* Build type objects for the source file. Sets the import table field for
* the source.
*/
public Node buildTypes(TypeBuilder tb) throws SemanticException {
ImportTable it = tb.importTable();
// Clear the import table in case we use the same visitor
// to visit a different source file.
tb.setImportTable(null);
return importTable(it);
}
public Context enterScope(Context c) {
c = c.pushSource(importTable);
c = c.pushBlock();
for (Iterator i = decls.iterator(); i.hasNext();) {
TopLevelDecl d = (TopLevelDecl) i.next();
Named n = (Named) d.declaration();
c.addNamed(n);
}
return c;
}
/** Type check the source file. */
public Node typeCheck(TypeChecker tc) throws SemanticException {
Set names = new HashSet();
boolean hasPublic = false;
for (Iterator i = decls.iterator(); i.hasNext();) {
TopLevelDecl d = (TopLevelDecl) i.next();
String s = d.name();
if (names.contains(s)) {
throw new SemanticException("Duplicate declaration: \"" + s +
"\".", d.position());
}
names.add(s);
if (d.flags().isPublic()) {
if (hasPublic) {
throw new SemanticException(
"The source contains more than one public declaration.",
d.position());
}
hasPublic = true;
}
}
return this;
}
public String toString() {
return "<<<< " + source + " >>>>";
}
/** Write the source file to an output file. */
public void prettyPrint(CodeWriter w, PrettyPrinter tr) {
w.write("<<<< " + source + " >>>>");
w.newline(0);
if (package_ != null) {
w.write("package ");
print(package_, w, tr);
w.write(";");
w.newline(0);
w.newline(0);
}
for (Iterator i = imports.iterator(); i.hasNext(); ) {
Import im = (Import) i.next();
print(im, w, tr);
}
if (! imports.isEmpty()) {
w.newline(0);
}
for (Iterator i = decls.iterator(); i.hasNext(); ) {
TopLevelDecl d = (TopLevelDecl) i.next();
print(d, w, tr);
}
}
}