Search in sources :

Example 1 with Statement

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;
}
Also used : Statement(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement)

Example 2 with Statement

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);
        }
    }
}
Also used : HashMap(java.util.HashMap) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) Statement(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement) SpecifierStatement(org.eclipse.ceylon.compiler.typechecker.tree.Tree.SpecifierStatement) ArrayList(java.util.ArrayList) Statement(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 3 with Statement

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;
}
Also used : TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Statement(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 4 with Statement

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;
}
Also used : Return(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Return) JCExpressionStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpressionStatement) Statement(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) ForStatement(org.eclipse.ceylon.compiler.typechecker.tree.Tree.ForStatement) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) Statement(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) ConditionScope(org.eclipse.ceylon.model.typechecker.model.ConditionScope) ConditionScope(org.eclipse.ceylon.model.typechecker.model.ConditionScope) HasErrorException(org.eclipse.ceylon.compiler.java.codegen.recovery.HasErrorException) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree)

Example 5 with Statement

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();
}
Also used : ClassOrInterface(org.eclipse.ceylon.compiler.typechecker.tree.Tree.ClassOrInterface) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) SourceDeclarationVisitor(org.eclipse.ceylon.compiler.java.loader.SourceDeclarationVisitor) List(org.eclipse.ceylon.langtools.tools.javac.util.List) Declaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Declaration) JCMethodDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCMethodDecl) Stack(java.util.Stack) JCTypeParameter(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCTypeParameter) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) PackageDescriptor(org.eclipse.ceylon.compiler.typechecker.tree.Tree.PackageDescriptor) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Declaration(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Declaration) ClassOrInterface(org.eclipse.ceylon.compiler.typechecker.tree.Tree.ClassOrInterface) Statement(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement) JCStatement(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) JCVariableDecl(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl) ModuleDescriptor(org.eclipse.ceylon.compiler.typechecker.tree.Tree.ModuleDescriptor) Parameter(org.eclipse.ceylon.model.typechecker.model.Parameter) JCTypeParameter(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCTypeParameter)

Aggregations

Statement (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Statement)8 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)7 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)3 JCStatement (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)3 Constructor (org.eclipse.ceylon.model.typechecker.model.Constructor)3 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)3 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)3 HashMap (java.util.HashMap)2 HasErrorException (org.eclipse.ceylon.compiler.java.codegen.recovery.HasErrorException)2 CustomTree (org.eclipse.ceylon.compiler.typechecker.tree.CustomTree)2 AttributeDeclaration (org.eclipse.ceylon.compiler.typechecker.tree.Tree.AttributeDeclaration)2 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)2 Parameter (org.eclipse.ceylon.model.typechecker.model.Parameter)2 Value (org.eclipse.ceylon.model.typechecker.model.Value)2 ArrayList (java.util.ArrayList)1 Stack (java.util.Stack)1 Drop (org.eclipse.ceylon.compiler.java.codegen.recovery.Drop)1 SourceDeclarationVisitor (org.eclipse.ceylon.compiler.java.loader.SourceDeclarationVisitor)1 ClassOrInterface (org.eclipse.ceylon.compiler.typechecker.tree.Tree.ClassOrInterface)1 Declaration (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Declaration)1