use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement in project ceylon by eclipse.
the class GenerateJsVisitor method visitStatements.
void visitStatements(List<? extends Statement> statements) {
List<String> oldRetainedVars = retainedVars.reset(null);
final List<? extends Statement> prevStatements = currentStatements;
currentStatements = statements;
for (int i = 0; i < statements.size(); i++) {
Statement s = statements.get(i);
s.visit(this);
if (!opts.isMinify())
beginNewLine();
retainedVars.emitRetainedVars(this);
}
retainedVars.reset(oldRetainedVars);
currentStatements = prevStatements;
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement in project ceylon by eclipse.
the class MethodOrValueReferenceVisitor method visit.
@Override
public void visit(Tree.ClassDefinition that) {
if (!that.getDeclarationModel().hasConstructors()) {
boolean cs = enterCapturingScope();
super.visit(that);
exitCapturingScope(cs);
} else {
// super special case for unshared members when we have constructors
if (!declaration.isCaptured() && declaration instanceof FunctionOrValue && declaration.isClassMember()) {
Map<Constructor, ConstructorPlan> constructorPlans = new HashMap<Constructor, ConstructorPlan>();
List<Tree.Statement> statements = new ArrayList<>(that.getClassBody().getStatements().size());
// find every constructor, and build a model of how they delegate
for (Tree.Statement stmt : that.getClassBody().getStatements()) {
if (stmt instanceof Tree.Constructor) {
Tree.Constructor ctor = (Tree.Constructor) stmt;
// build a new plan for it
ConstructorPlan plan = new ConstructorPlan();
plan.constructor = ctor;
constructorPlans.put(ctor.getConstructor(), plan);
// find every constructor which delegates to another constructor
if (ctor.getDelegatedConstructor() != null && ctor.getDelegatedConstructor().getInvocationExpression() != null) {
if (ctor.getDelegatedConstructor().getInvocationExpression().getPrimary() instanceof Tree.ExtendedTypeExpression) {
Tree.ExtendedTypeExpression ete = (Tree.ExtendedTypeExpression) ctor.getDelegatedConstructor().getInvocationExpression().getPrimary();
// are we delegating to a constructor (not a supertype) of the same class (this class)?
if (Decl.isConstructor(ete.getDeclaration()) && ModelUtil.getConstructedClass(ete.getDeclaration()).equals(that.getDeclarationModel())) {
// remember the delegation
Constructor delegate = ModelUtil.getConstructor(ete.getDeclaration());
ConstructorPlan delegatePlan = constructorPlans.get(delegate);
plan.delegate = delegatePlan;
// mark the delegate as delegated
delegatePlan.isDelegate = true;
// we have all the statements before us and after our delegate
plan.before.addAll(delegatePlan.after);
}
}
}
// if we have no delegate, we start with every common statement
if (plan.delegate == null)
plan.before.addAll(statements);
// also add all the constructor's statements
if (ctor.getBlock() != null) {
plan.before.addAll(ctor.getBlock().getStatements());
}
} else {
statements.add(stmt);
// make sure all existing constructors get this statement too
for (ConstructorPlan constructorPlan : constructorPlans.values()) constructorPlan.after.add(stmt);
}
}
// try every constructor plan and see if it's used in two methods
for (ConstructorPlan constructorPlan : constructorPlans.values()) {
visitConstructorPlan(constructorPlan);
// are we done?
if (declaration.isCaptured())
break;
}
}
// do regular capturing after that (for members), if required
if (!declaration.isCaptured()) {
boolean cs = enterCapturingScope();
super.visit(that);
exitCapturingScope(cs);
}
}
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement in project ceylon by eclipse.
the class MethodOrValueReferenceVisitor method usedIn.
/**
* Returns 1 if the declaration is captured in the given statements, 0 otherwise.
*/
private int usedIn(List<Statement> stmts) {
for (Tree.Statement stmt : stmts) {
// count declarations as usage
if (stmt instanceof Tree.TypedDeclaration) {
Tree.TypedDeclaration td = (Tree.TypedDeclaration) stmt;
if (td.getDeclarationModel() == declaration)
return 1;
}
stmt.visit(this);
if (declaration.isCaptured())
break;
}
boolean used = declaration.isCaptured();
FunctionOrValue fov = (FunctionOrValue) declaration;
fov.setCaptured(false);
if (fov instanceof Value) {
Value val = (Value) fov;
if (val.getSetter() != null)
val.getSetter().setCaptured(false);
}
return used ? 1 : 0;
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement in project ceylon by eclipse.
the class StatementTransformer method transformBlock.
public List<JCStatement> transformBlock(Tree.Block block, boolean revertRet) {
if (block == null) {
return List.<JCStatement>nil();
}
at(block);
CeylonVisitor v = gen().visitor;
final ListBuffer<JCTree> prevDefs = v.defs;
final boolean prevInInitializer = v.inInitializer;
final ClassDefinitionBuilder prevClassBuilder = v.classBuilder;
Tree.Block oldBlock = block;
currentBlock = block;
List<JCStatement> result;
try {
v.defs = new ListBuffer<JCTree>();
v.inInitializer = false;
v.classBuilder = current();
pushBlockImports(block);
java.util.Iterator<Statement> statements = block.getStatements().iterator();
while (statements.hasNext()) {
Tree.Statement stmt = statements.next();
Transformer<JCStatement, Return> returnTransformer;
if (revertRet && stmt instanceof Tree.Declaration) {
returnTransformer = returnTransformer(defaultReturnTransformer);
} else {
returnTransformer = this.returnTransformer;
}
try {
HasErrorException error = errors().getFirstErrorBlock(stmt);
if (error == null) {
stmt.visit(v);
} else {
v.append(this.makeThrowUnresolvedCompilationError(error));
break;
}
} finally {
returnTransformer(returnTransformer);
}
}
popBlockImports(block);
result = (List<JCStatement>) v.getResult().toList();
Runnable r = onEndBlock.get(block);
if (r != null) {
r.run();
}
} finally {
v.classBuilder = prevClassBuilder;
v.inInitializer = prevInInitializer;
v.defs = prevDefs;
// Close Substitutions which were scoped to this block
Scope scope = block.getScope();
while (scope instanceof ConditionScope) {
scope = scope.getScope();
}
naming.closeScopedSubstitutions(scope);
currentBlock = oldBlock;
}
return result;
}
use of org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement in project ceylon by eclipse.
the class CeylonTransformer method makeDefs.
private List<JCTree> makeDefs(CompilationUnit t) {
final ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
t.visit(new SourceDeclarationVisitor() {
@Override
public void loadFromSource(Declaration decl) {
if (!checkNative(decl))
return;
Stack<Tree.Declaration> ancestors = new Stack<>();
long flags = decl instanceof Tree.AnyInterface ? Flags.INTERFACE : 0;
String name = Naming.toplevelClassName("", decl);
defs.add(makeClassDef(decl, flags, name, WantedDeclaration.Normal, defs, ancestors));
if (decl instanceof Tree.AnyInterface) {
String implName = Naming.getImplClassName(name);
defs.add(makeClassDef(decl, 0, implName, WantedDeclaration.InterfaceImpl, defs, ancestors));
}
if (Decl.isAnnotationClassNoModel(decl)) {
String annotationName = Naming.suffixName(Suffix.$annotation$, name);
defs.add(makeClassDef(decl, Flags.ANNOTATION | Flags.INTERFACE, annotationName, WantedDeclaration.Annotation, defs, ancestors));
if (Decl.isSequencedAnnotationClassNoModel((Tree.AnyClass) decl)) {
String annotationsName = Naming.suffixName(Suffix.$annotations$, name);
defs.add(makeClassDef(decl, Flags.ANNOTATION | Flags.INTERFACE, annotationsName, WantedDeclaration.AnnotationSequence, defs, ancestors));
}
}
}
private JCTree makeClassDef(Tree.Declaration decl, long flags, String name, WantedDeclaration wantedDeclaration, ListBuffer<JCTree> toplevelDeclarations, Stack<Tree.Declaration> ancestors) {
if (decl instanceof Tree.AnyInterface == false && TreeUtil.hasAnnotation(decl.getAnnotationList(), "static", null)) {
flags |= Flags.STATIC;
}
ListBuffer<JCTree.JCTypeParameter> typarams = new ListBuffer<JCTree.JCTypeParameter>();
if (decl instanceof Tree.ClassOrInterface) {
Tree.ClassOrInterface classDecl = (ClassOrInterface) decl;
if (decl instanceof Tree.AnyInterface) {
// interfaces are pulled up and catch container type params
for (Tree.Declaration ancestor : ancestors) {
if (ancestor instanceof Tree.ClassOrInterface) {
addTypeParameters(typarams, (Tree.ClassOrInterface) ancestor);
}
}
}
addTypeParameters(typarams, classDecl);
}
ancestors.push(decl);
JCTree ret = make().ClassDef(make().Modifiers(flags | Flags.PUBLIC), names().fromString(name), typarams.toList(), null, List.<JCExpression>nil(), makeClassBody(decl, wantedDeclaration, toplevelDeclarations, ancestors));
ancestors.pop();
return ret;
}
private void addTypeParameters(ListBuffer<JCTypeParameter> typarams, Tree.ClassOrInterface classDecl) {
if (classDecl.getTypeParameterList() != null) {
for (Tree.TypeParameterDeclaration typeParamDecl : classDecl.getTypeParameterList().getTypeParameterDeclarations()) {
// we don't need a valid name, just a name, and making it BOGUS helps us find it later if it turns out
// we failed to reset everything properly
typarams.add(make().TypeParameter(names().fromString("BOGUS-" + typeParamDecl.getIdentifier().getText()), List.<JCExpression>nil()));
}
}
}
private List<JCTree> makeClassBody(Declaration decl, WantedDeclaration wantedDeclaration, ListBuffer<JCTree> toplevelDeclarations, Stack<Tree.Declaration> ancestors) {
// only do it for Bootstrap where we control the annotations, because it's so dodgy ATM
if (wantedDeclaration == WantedDeclaration.Annotation) {
ListBuffer<JCTree> body = new ListBuffer<JCTree>();
for (Tree.Parameter param : ((Tree.ClassDefinition) decl).getParameterList().getParameters()) {
String name;
JCExpression type = make().TypeArray(make().Type(syms().stringType));
if (param instanceof Tree.InitializerParameter)
name = ((Tree.InitializerParameter) param).getIdentifier().getText();
else if (param instanceof Tree.ParameterDeclaration) {
Tree.TypedDeclaration typedDeclaration = ((Tree.ParameterDeclaration) param).getTypedDeclaration();
name = typedDeclaration.getIdentifier().getText();
type = getAnnotationTypeFor(typedDeclaration.getType());
} else
name = "ERROR";
JCMethodDecl method = make().MethodDef(make().Modifiers(Flags.PUBLIC), names().fromString(name), type, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
body.append(method);
}
return body.toList();
}
if (wantedDeclaration == WantedDeclaration.AnnotationSequence) {
String name = Naming.toplevelClassName("", decl);
String annotationName = Naming.suffixName(Suffix.$annotation$, name);
JCExpression type = make().TypeArray(make().Ident(names().fromString(annotationName)));
JCMethodDecl method = make().MethodDef(make().Modifiers(Flags.PUBLIC), names().fromString("value"), type, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null);
return List.<JCTree>of(method);
}
ListBuffer<JCTree> defs = new ListBuffer<>();
java.util.List<Statement> statements = null;
if (decl instanceof Tree.ClassDefinition)
statements = ((Tree.ClassDefinition) decl).getClassBody().getStatements();
else if (decl instanceof Tree.InterfaceDefinition) {
// only walk interface members if we're generating the impl class
if (wantedDeclaration == WantedDeclaration.InterfaceImpl)
statements = ((Tree.InterfaceDefinition) decl).getInterfaceBody().getStatements();
}
if (statements != null) {
for (Tree.Statement member : statements) {
if (member instanceof Tree.ClassOrInterface && checkNative((Tree.Declaration) member)) {
long flags = member instanceof Tree.AnyInterface ? Flags.INTERFACE : 0;
String initialName = Naming.toplevelClassName("", (Tree.Declaration) member);
String name;
if (member instanceof Tree.AnyInterface) {
// interfaces are pulled to the toplevel
StringBuffer strbuf = new StringBuffer();
for (Tree.Declaration part : ancestors) strbuf.append(part.getIdentifier().getText()).append("$");
name = strbuf.append(initialName).toString();
} else {
name = initialName;
}
JCTree def = makeClassDef((Tree.Declaration) member, flags, name, WantedDeclaration.Normal, toplevelDeclarations, ancestors);
if (member instanceof Tree.AnyInterface) {
toplevelDeclarations.add(def);
String implName = Naming.getImplClassName(initialName);
defs.add(makeClassDef((Tree.Declaration) member, 0, implName, WantedDeclaration.InterfaceImpl, defs, ancestors));
} else
defs.add(def);
// FIXME: interfaces impl?
}
}
}
return defs.toList();
}
private JCExpression getAnnotationTypeFor(Tree.Type type) {
if (type instanceof Tree.BaseType) {
String name = ((Tree.BaseType) type).getIdentifier().getText();
if (name.equals("String") || name.equals("Declaration"))
return make().Type(syms().stringType);
if (name.equals("Boolean"))
return make().Type(syms().booleanType);
if (name.equals("Integer"))
return make().Type(syms().longType);
if (name.equals("Float"))
return make().Type(syms().doubleType);
if (name.equals("Byte"))
return make().Type(syms().byteType);
if (name.equals("Character"))
return make().Type(syms().charType);
if (name.equals("Declaration") || name.equals("ClassDeclaration") || name.equals("InterfaceDeclaration") || name.equals("ClassOrInterfaceDeclaration"))
return make().Type(syms().stringType);
// probably an enum value then
return make().TypeArray(make().Type(syms().stringType));
}
if (type instanceof Tree.SequencedType) {
return make().TypeArray(getAnnotationTypeFor(((Tree.SequencedType) type).getType()));
}
if (type instanceof Tree.SequenceType) {
return make().TypeArray(getAnnotationTypeFor(((Tree.SequenceType) type).getElementType()));
}
if (type instanceof Tree.IterableType) {
return make().TypeArray(getAnnotationTypeFor(((Tree.IterableType) type).getElementType()));
}
if (type instanceof Tree.TupleType) {
// can only be one, must be a SequencedType
Tree.Type sequencedType = ((Tree.TupleType) type).getElementTypes().get(0);
return getAnnotationTypeFor(sequencedType);
}
System.err.println("Unknown Annotation type: " + type);
return make().TypeArray(make().Type(syms().stringType));
}
@Override
public void loadFromSource(ModuleDescriptor that) {
// don't think we care about these
}
@Override
public void loadFromSource(PackageDescriptor that) {
// don't think we care about these
}
});
return defs.toList();
}
Aggregations