/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2010.
*/
package x10rose;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import polyglot.ast.ClassMember;
import polyglot.ast.Node;
import polyglot.ast.NodeFactory;
import polyglot.ast.SourceFile;
import polyglot.ast.TopLevelDecl;
import polyglot.ast.TypeNode;
import polyglot.frontend.Compiler;
import polyglot.frontend.CyclicDependencyException;
import polyglot.frontend.ForgivingVisitorGoal;
import polyglot.frontend.Goal;
import polyglot.frontend.JLScheduler;
import polyglot.frontend.Job;
import polyglot.frontend.OutputGoal;
import polyglot.frontend.ParserGoal;
import polyglot.frontend.Scheduler;
import polyglot.frontend.Source;
import polyglot.frontend.SourceGoal;
import polyglot.frontend.SourceGoal_c;
import polyglot.frontend.VisitorGoal;
import polyglot.main.Options;
import polyglot.types.Flags;
import polyglot.types.SemanticException;
import polyglot.types.TypeSystem;
import polyglot.util.ErrorQueue;
import polyglot.util.Position;
import polyglot.visit.ConformanceChecker;
import polyglot.visit.ConstructorCallChecker;
import polyglot.visit.ExceptionChecker;
import polyglot.visit.ExitChecker;
import polyglot.visit.FwdReferenceChecker;
import polyglot.visit.InitChecker;
import polyglot.visit.PostCompiled;
import polyglot.visit.PruningVisitor;
import polyglot.visit.ReachChecker;
import x10.Version;
import x10.X10CompilerOptions;
import x10.ast.X10ClassDecl;
import x10.extension.X10Ext;
import x10.visit.AnnotationChecker;
import x10.visit.CheckEscapingThis;
import x10.visit.ErrChecker;
import x10.visit.IfdefVisitor;
import x10.visit.X10TypeBuilder;
import x10.visit.X10TypeChecker;
import x10rose.visit.RoseTranslator;
/**
* Extension information for x10 extension.
*/
public class ExtensionInfo extends x10.ExtensionInfo {
/*** Construct an ExtensionInfo */
public polyglot.main.Version version() {
return new Version() {
public String name() { return "x10rose"; }
};
}
public String[] fileExtensions() {
return new String[] { "x10" };
}
public String compilerName() {
return "x10rose";
}
// ==================================================
// Scheduling of compiler passes for the Rose backend
// ==================================================
protected Scheduler createScheduler() {
return new X10Scheduler(this);
}
public static class X10Scheduler extends JLScheduler {
public X10Scheduler(ExtensionInfo extInfo) {
super(extInfo);
}
public ExtensionInfo extensionInfo() {
return (ExtensionInfo) this.extInfo;
}
public List<Goal> goals(Job job) {
List<Goal> goals = new ArrayList<Goal>();
// PARSE
goals.add(Parsed(job));
// TYPE CHECK
X10CompilerOptions opts = extensionInfo().getOptions();
if (opts.x10_config.CHECK_ERR_MARKERS) goals.add(ErrChecker(job)); // must be the first phase after parsing because later phases might fail and stop type checking (it shouldn't happen, but it does)
goals.add(ImportTableInitialized(job));
goals.add(TypesInitialized(job));
goals.add(PropagateAnnotations(job));
goals.add(PreTypeCheck(job));
goals.add(Ifdef(job));
goals.add(TypesInitializedForCommandLineBarrier());
goals.add(TypeChecked(job));
goals.add(ReassembleAST(job));
// 'SEMANTIC' CHECKS
// check that types are consistent (e.g. constraints are not inconsistent)
goals.add(ConformanceChecked(job));
// Data-flow analyses
goals.add(ReachabilityChecked(job)); // This must be the first dataflow analysis (see DataFlow.reportCFG_Errors)
goals.add(ExceptionsChecked(job));
goals.add(ExitPathsChecked(job));
goals.add(InitializationsChecked(job));
goals.add(ConstructorCallsChecked(job));
goals.add(CheckEscapingThis(job));
goals.add(AnnotationChecker(job));
goals.add(CheckASTForErrors(job));
goals.add(RoseHandoff(job));
goals.add(End(job));
return goals;
}
protected Goal PostCompiled() {
return new PostCompiled(extInfo) {
private static final long serialVersionUID = 1834245937046911633L;
protected boolean invokePostCompiler(Options options, Compiler compiler, ErrorQueue eq) {
if (System.getProperty("x10.postcompile", "TRUE").equals("FALSE"))
return true;
// invoke rose postcompiler
return true;
}
}.intern(this);
}
public Goal CheckASTForErrors(Job job) {
return new SourceGoal_c("CheckASTForErrors", job) {
private static final long serialVersionUID = 565345690079406384L;
public boolean runTask() {
if (job.reportedErrors()) {
Node ast = job.ast();
job.ast(((X10Ext)ast.ext()).setSubtreeValid(false));
}
return true;
}
}.intern(this);
}
public Goal PropagateAnnotations(Job job) {
// ###
return new VisitorGoal("PropagateAnnotations", job, new PruningVisitor()).intern(this);
}
@Override
public Goal InitializationsChecked(Job job) {
TypeSystem ts = job.extensionInfo().typeSystem();
NodeFactory nf = job.extensionInfo().nodeFactory();
return new ForgivingVisitorGoal("InitializationsChecked", job, new InitChecker(job, ts, nf)).intern(this);
}
public Goal RoseHandoff(Job job) {
Goal cg = new OutputGoal(job, new RoseTranslator(job, extInfo.typeSystem(), extInfo.nodeFactory(), extInfo.targetFactory()));
return cg.intern(this);
}
static class X10ParserGoal extends ParserGoal {
private static final long serialVersionUID = 6811976416160592748L;
public X10ParserGoal(Compiler compiler, Job job) {
super(compiler, job);
}
@Override
protected SourceFile createDummyAST() {
NodeFactory nf = job().extensionInfo().nodeFactory();
String fName = job.source().name();
Position pos = new Position("", job.source().path(), 1, 1).markCompilerGenerated();
String name = fName.substring(fName.lastIndexOf(File.separatorChar)+1, fName.lastIndexOf('.'));
X10ClassDecl decl = (X10ClassDecl) nf.ClassDecl(pos, nf.FlagsNode(pos, Flags.PUBLIC),
nf.Id(pos, name), null, Collections.<TypeNode>emptyList(),
nf.ClassBody(pos, Collections.<ClassMember>emptyList()));
decl = decl.errorInAST(new SemanticException("", pos));
SourceFile ast = nf.SourceFile(pos, Collections.<TopLevelDecl>singletonList(decl)).source(job.source());
ast = (SourceFile) ((X10Ext)ast.ext()).setSubtreeValid(false);
return ast;
}
}
@Override
public Goal Parsed(Job job) {
return new X10ParserGoal(extInfo.compiler(), job).intern(this);
}
@Override
public Goal constructTypesInitialized(Job job) {
TypeSystem ts = job.extensionInfo().typeSystem();
NodeFactory nf = job.extensionInfo().nodeFactory();
return new ForgivingVisitorGoal("TypesInitialized", job, new X10TypeBuilder(job, ts, nf)).intern(this);
}
@Override
public Goal TypeChecked(Job job) {
TypeSystem ts = job.extensionInfo().typeSystem();
NodeFactory nf = job.extensionInfo().nodeFactory();
return new ForgivingVisitorGoal("TypeChecked", job, new X10TypeChecker(job, ts, nf, job.nodeMemo())).intern(this);
}
public Goal ConformanceChecked(Job job) {
TypeSystem ts = job.extensionInfo().typeSystem();
NodeFactory nf = job.extensionInfo().nodeFactory();
return new ForgivingVisitorGoal("ConformanceChecked", job, new ConformanceChecker(job, ts, nf)).intern(this);
}
public Goal ReachabilityChecked(Job job) {
TypeSystem ts = job.extensionInfo().typeSystem();
NodeFactory nf = job.extensionInfo().nodeFactory();
return new ForgivingVisitorGoal("ReachChecked", job, new ReachChecker(job, ts, nf)).intern(this);
}
public Goal ExceptionsChecked(Job job) {
TypeSystem ts = job.extensionInfo().typeSystem();
NodeFactory nf = job.extensionInfo().nodeFactory();
return new ForgivingVisitorGoal("ExceptionsChecked", job, new ExceptionChecker(job, ts, nf)).intern(this);
}
public Goal ExitPathsChecked(Job job) {
TypeSystem ts = job.extensionInfo().typeSystem();
NodeFactory nf = job.extensionInfo().nodeFactory();
return new ForgivingVisitorGoal("ExitChecked", job, new ExitChecker(job, ts, nf)).intern(this);
}
public Goal ConstructorCallsChecked(Job job) {
TypeSystem ts = job.extensionInfo().typeSystem();
NodeFactory nf = job.extensionInfo().nodeFactory();
return new ForgivingVisitorGoal("ContructorCallsChecked", job, new ConstructorCallChecker(job, ts, nf)).intern(this);
}
public Goal ForwardReferencesChecked(Job job) {
TypeSystem ts = job.extensionInfo().typeSystem();
NodeFactory nf = job.extensionInfo().nodeFactory();
return new ForgivingVisitorGoal("ForwardRefsChecked", job, new FwdReferenceChecker(job, ts, nf)).intern(this);
}
public Goal CheckEscapingThis(Job job) {
return new ForgivingVisitorGoal("CheckEscapingThis", job, new CheckEscapingThis.Main(job)).intern(this);
}
private Goal AnnotationChecker(Job job) {
return new ForgivingVisitorGoal("AnnotationChecker", job, new AnnotationChecker(job,job.extensionInfo().typeSystem(),job.extensionInfo().nodeFactory())).intern(this);
}
private Goal Ifdef(Job job) {
return new ForgivingVisitorGoal("IfdefVisitor", job, new IfdefVisitor(job,job.extensionInfo().typeSystem(),job.extensionInfo().nodeFactory())).intern(this);
}
private Goal ErrChecker(Job job) {
return new ForgivingVisitorGoal("ErrChecker", job, new ErrChecker(job)).intern(this);
}
@Override
protected Job createSourceJob(Source source, Node ast) {
return new x10.ExtensionInfo.X10Scheduler.X10Job(extInfo, extInfo.jobExt(), source, ast);
}
@Override
protected boolean runPass(Goal goal) throws CyclicDependencyException {
Job job = goal instanceof SourceGoal ? ((SourceGoal) goal).job() : null;
int savedInitialErrorCount = -1;
if (job != null)
savedInitialErrorCount = ((x10.ExtensionInfo.X10Scheduler.X10Job) job).initialErrorCount();
boolean result = super.runPass(goal);
if (job != null)
((x10.ExtensionInfo.X10Scheduler.X10Job) job).initialErrorCount(savedInitialErrorCount);
return result;
}
}
}