Search in sources :

Example 21 with JCTree

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree in project ceylon by eclipse.

the class Lower method visitConditional.

// Simplify conditionals with known constant controlling expressions.
// This allows us to avoid generating supporting declarations for
// the dead code, which will not be eliminated during code generation.
// Note that Flow.isFalse and Flow.isTrue only return true
// for constant expressions in the sense of JLS 15.27, which
// are guaranteed to have no side-effects.  More aggressive
// constant propagation would require that we take care to
// preserve possible side-effects in the condition expression.
/**
 * Visitor method for conditional expressions.
 */
@Override
public void visitConditional(JCConditional tree) {
    JCTree cond = tree.cond = translate(tree.cond, syms.booleanType);
    if (cond.type.isTrue()) {
        result = convert(translate(tree.truepart, tree.type), tree.type);
        addPrunedInfo(cond);
    } else if (cond.type.isFalse()) {
        result = convert(translate(tree.falsepart, tree.type), tree.type);
        addPrunedInfo(cond);
    } else {
        // Condition is not a compile-time constant.
        tree.truepart = translate(tree.truepart, tree.type);
        tree.falsepart = translate(tree.falsepart, tree.type);
        result = tree;
    }
}
Also used : JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)

Example 22 with JCTree

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree in project ceylon by eclipse.

the class Lower method visitAssignop.

public void visitAssignop(final JCAssignOp tree) {
    JCTree lhsAccess = access(TreeInfo.skipParens(tree.lhs));
    final boolean boxingReq = !tree.lhs.type.isPrimitive() && tree.operator.type.getReturnType().isPrimitive();
    if (boxingReq || lhsAccess.hasTag(APPLY)) {
        // boxing required; need to rewrite as x = (unbox typeof x)(x op y);
        // or if x == (typeof x)z then z = (unbox typeof x)((typeof x)z op y)
        // (but without recomputing x)
        JCTree newTree = abstractLval(tree.lhs, new TreeBuilder() {

            public JCTree build(final JCTree lhs) {
                JCTree.Tag newTag = tree.getTag().noAssignOp();
                // Erasure (TransTypes) can change the type of
                // tree.lhs.  However, we can still get the
                // unerased type of tree.lhs as it is stored
                // in tree.type in Attr.
                Symbol newOperator = rs.resolveBinaryOperator(tree.pos(), newTag, attrEnv, tree.type, tree.rhs.type);
                JCExpression expr = (JCExpression) lhs;
                if (expr.type != tree.type)
                    expr = make.TypeCast(tree.type, expr);
                JCBinary opResult = make.Binary(newTag, expr, tree.rhs);
                opResult.operator = newOperator;
                opResult.type = newOperator.type.getReturnType();
                JCExpression newRhs = boxingReq ? make.TypeCast(types.unboxedType(tree.type), opResult) : opResult;
                return make.Assign((JCExpression) lhs, newRhs).setType(tree.type);
            }
        });
        result = translate(newTree);
        return;
    }
    tree.lhs = translate(tree.lhs, tree);
    tree.rhs = translate(tree.rhs, tree.operator.type.getParameterTypes().tail.head);
    // right hand side as last argument of the access method.
    if (tree.lhs.hasTag(APPLY)) {
        JCMethodInvocation app = (JCMethodInvocation) tree.lhs;
        // if operation is a += on strings,
        // make sure to convert argument to string
        JCExpression rhs = (((OperatorSymbol) tree.operator).opcode == string_add) ? makeString(tree.rhs) : tree.rhs;
        app.args = List.of(rhs).prependList(app.args);
        result = app;
    } else {
        result = tree;
    }
}
Also used : Symbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) TypeTag(org.eclipse.ceylon.langtools.tools.javac.code.TypeTag) Tag(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.Tag)

Example 23 with JCTree

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree in project ceylon by eclipse.

the class MemberEnter method DefaultConstructor.

/* ***************************************************************************
 * tree building
 ****************************************************************************/
/**
 * Generate default constructor for given class. For classes different
 *  from java.lang.Object, this is:
 *
 *    c(argtype_0 x_0, ..., argtype_n x_n) throws thrown {
 *      super(x_0, ..., x_n)
 *    }
 *
 *  or, if based == true:
 *
 *    c(argtype_0 x_0, ..., argtype_n x_n) throws thrown {
 *      x_0.super(x_1, ..., x_n)
 *    }
 *
 *  @param make     The tree factory.
 *  @param c        The class owning the default constructor.
 *  @param argtypes The parameter types of the constructor.
 *  @param thrown   The thrown exceptions of the constructor.
 *  @param based    Is first parameter a this$n?
 */
JCTree DefaultConstructor(TreeMaker make, ClassSymbol c, MethodSymbol baseInit, List<Type> typarams, List<Type> argtypes, List<Type> thrown, long flags, boolean based) {
    JCTree result;
    if ((c.flags() & ENUM) != 0 && (types.supertype(c.type).tsym == syms.enumSym)) {
        // constructors of true enums are private
        flags = (flags & ~AccessFlags) | PRIVATE | GENERATEDCONSTR;
    } else
        flags |= (c.flags() & AccessFlags) | GENERATEDCONSTR;
    if (c.name.isEmpty()) {
        flags |= ANONCONSTR;
    }
    Type mType = new MethodType(argtypes, null, thrown, c);
    Type initType = typarams.nonEmpty() ? new ForAll(typarams, mType) : mType;
    MethodSymbol init = new MethodSymbol(flags, names.init, initType, c);
    init.params = createDefaultConstructorParams(make, baseInit, init, argtypes, based);
    List<JCVariableDecl> params = make.Params(argtypes, init);
    List<JCStatement> stats = List.nil();
    if (c.type != syms.objectType) {
        stats = stats.prepend(SuperCall(make, typarams, params, based));
    }
    result = make.MethodDef(init, make.Block(0, stats));
    return result;
}
Also used : Type(org.eclipse.ceylon.langtools.tools.javac.code.Type) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)

Example 24 with JCTree

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree in project ceylon by eclipse.

the class MemberEnter method complete.

/* ********************************************************************
 * Source completer
 *********************************************************************/
/**
 * Complete entering a class.
 *  @param sym         The symbol of the class to be completed.
 */
public void complete(Symbol sym) throws CompletionFailure {
    // Suppress some (recursive) MemberEnter invocations
    if (!completionEnabled) {
        // Re-install same completer for next time around and return.
        Assert.check((sym.flags() & Flags.COMPOUND) == 0);
        sym.completer = this;
        return;
    }
    ClassSymbol c = (ClassSymbol) sym;
    ClassType ct = (ClassType) c.type;
    Env<AttrContext> env = typeEnvs.get(c);
    JCClassDecl tree = (JCClassDecl) env.tree;
    boolean wasFirst = isFirst;
    isFirst = false;
    try {
        annotate.enterStart();
        JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
        DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
        try {
            // Save class environment for later member enter (2) processing.
            halfcompleted.append(env);
            // Mark class as not yet attributed.
            c.flags_field |= UNATTRIBUTED;
            // clauses have been seen.
            if (c.owner.kind == PCK) {
                memberEnter(env.toplevel, env.enclosing(TOPLEVEL));
                todo.append(env);
            }
            if (c.owner.kind == TYP)
                c.owner.complete();
            // create an environment for evaluating the base clauses
            Env<AttrContext> baseEnv = baseEnv(tree, env);
            if (tree.extending != null)
                typeAnnotate(tree.extending, baseEnv, sym, tree.pos());
            for (JCExpression impl : tree.implementing) typeAnnotate(impl, baseEnv, sym, tree.pos());
            annotate.flush();
            // Determine supertype.
            Type supertype = (tree.extending != null) ? attr.attribBase(tree.extending, baseEnv, true, false, true) : ((tree.mods.flags & Flags.ENUM) != 0) ? attr.attribBase(enumBase(tree.pos, c), baseEnv, true, false, false) : (c.fullname == names.java_lang_Object) ? Type.noType : syms.objectType;
            ct.supertype_field = modelMissingTypes(supertype, tree.extending, false);
            // Determine interfaces.
            ListBuffer<Type> interfaces = new ListBuffer<Type>();
            // lazy init
            ListBuffer<Type> all_interfaces = null;
            Set<Type> interfaceSet = new HashSet<Type>();
            List<JCExpression> interfaceTrees = tree.implementing;
            for (JCExpression iface : interfaceTrees) {
                Type i = attr.attribBase(iface, baseEnv, false, true, true);
                if (i.hasTag(CLASS)) {
                    interfaces.append(i);
                    if (all_interfaces != null)
                        all_interfaces.append(i);
                    chk.checkNotRepeated(iface.pos(), types.erasure(i), interfaceSet);
                } else {
                    if (all_interfaces == null)
                        all_interfaces = new ListBuffer<Type>().appendList(interfaces);
                    all_interfaces.append(modelMissingTypes(i, iface, true));
                }
            }
            if ((c.flags_field & Flags.ANNOTATION) != 0) {
                ct.interfaces_field = List.of(syms.annotationType);
                ct.all_interfaces_field = ct.interfaces_field;
            } else {
                ct.interfaces_field = interfaces.toList();
                ct.all_interfaces_field = (all_interfaces == null) ? ct.interfaces_field : all_interfaces.toList();
            }
            if (c.fullname == names.java_lang_Object) {
                if (tree.extending != null) {
                    chk.checkNonCyclic(tree.extending.pos(), supertype);
                    ct.supertype_field = Type.noType;
                } else if (tree.implementing.nonEmpty()) {
                    chk.checkNonCyclic(tree.implementing.head.pos(), ct.interfaces_field.head);
                    ct.interfaces_field = List.nil();
                }
            }
            // Annotations.
            // In general, we cannot fully process annotations yet,  but we
            // can attribute the annotation types and then check to see if the
            // @Deprecated annotation is present.
            attr.attribAnnotationTypes(tree.mods.annotations, baseEnv);
            if (hasDeprecatedAnnotation(tree.mods.annotations))
                c.flags_field |= DEPRECATED;
            annotateLater(tree.mods.annotations, baseEnv, c, tree.pos());
            // class type parameters use baseEnv but everything uses env
            chk.checkNonCyclicDecl(tree);
            attr.attribTypeVariables(tree.typarams, baseEnv);
            // Do this here, where we have the symbol.
            for (JCTypeParameter tp : tree.typarams) typeAnnotate(tp, baseEnv, sym, tree.pos());
            // Add default constructor if needed.
            if ((c.flags() & INTERFACE) == 0 && !TreeInfo.hasConstructors(tree.defs)) {
                List<Type> argtypes = List.nil();
                List<Type> typarams = List.nil();
                List<Type> thrown = List.nil();
                long ctorFlags = 0;
                boolean based = false;
                boolean addConstructor = true;
                JCNewClass nc = null;
                if (c.name.isEmpty()) {
                    nc = (JCNewClass) env.next.tree;
                    if (nc.constructor != null) {
                        addConstructor = nc.constructor.kind != ERR;
                        Type superConstrType = types.memberType(c.type, nc.constructor);
                        argtypes = superConstrType.getParameterTypes();
                        typarams = superConstrType.getTypeArguments();
                        ctorFlags = nc.constructor.flags() & VARARGS;
                        if (nc.encl != null) {
                            argtypes = argtypes.prepend(nc.encl.type);
                            based = true;
                        }
                        thrown = superConstrType.getThrownTypes();
                    }
                }
                if (addConstructor) {
                    MethodSymbol basedConstructor = nc != null ? (MethodSymbol) nc.constructor : null;
                    JCTree constrDef = DefaultConstructor(make.at(tree.pos), c, basedConstructor, typarams, argtypes, thrown, ctorFlags, based);
                    tree.defs = tree.defs.prepend(constrDef);
                }
            }
            // enter symbols for 'this' into current scope.
            VarSymbol thisSym = new VarSymbol(FINAL | HASINIT, names._this, c.type, c);
            thisSym.pos = Position.FIRSTPOS;
            env.info.scope.enter(thisSym);
            // if this is a class, enter symbol for 'super' into current scope.
            if ((c.flags_field & INTERFACE) == 0 && ct.supertype_field.hasTag(CLASS)) {
                VarSymbol superSym = new VarSymbol(FINAL | HASINIT, names._super, ct.supertype_field, c);
                superSym.pos = Position.FIRSTPOS;
                env.info.scope.enter(superSym);
            }
            // name as a top-level package.
            if (checkClash && c.owner.kind == PCK && c.owner != syms.unnamedPackage && reader.packageExists(c.fullname)) {
                log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), c);
            }
            if (c.owner.kind == PCK && (c.flags_field & PUBLIC) == 0 && !env.toplevel.sourcefile.isNameCompatible(c.name.toString(), JavaFileObject.Kind.SOURCE)) {
                c.flags_field |= AUXILIARY;
            }
        } catch (CompletionFailure ex) {
            chk.completionError(tree.pos(), ex);
        } finally {
            deferredLintHandler.setPos(prevLintPos);
            log.useSource(prev);
        }
        // classes in a second phase.
        if (wasFirst) {
            try {
                while (halfcompleted.nonEmpty()) {
                    Env<AttrContext> toFinish = halfcompleted.next();
                    finish(toFinish);
                    if (allowTypeAnnos) {
                        typeAnnotations.organizeTypeAnnotationsSignatures(toFinish, (JCClassDecl) toFinish.tree);
                        typeAnnotations.validateTypeAnnotationsSignatures(toFinish, (JCClassDecl) toFinish.tree);
                    }
                }
            } finally {
                isFirst = true;
            }
        }
    } finally {
        annotate.enterDone();
    }
}
Also used : JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) JavaFileObject(org.eclipse.ceylon.javax.tools.JavaFileObject) Type(org.eclipse.ceylon.langtools.tools.javac.code.Type) DiagnosticPosition(org.eclipse.ceylon.langtools.tools.javac.util.JCDiagnostic.DiagnosticPosition) HashSet(java.util.HashSet)

Example 25 with JCTree

use of org.eclipse.ceylon.langtools.tools.javac.tree.JCTree in project ceylon by eclipse.

the class Attr method visitApply.

/**
 * Visitor method for method invocations.
 *  NOTE: The method part of an application will have in its type field
 *        the return type of the method, not the method's type itself!
 */
public void visitApply(JCMethodInvocation tree) {
    // The local environment of a method application is
    // a new environment nested in the current one.
    Env<AttrContext> localEnv = env.dup(tree, env.info.dup());
    // The types of the actual method arguments.
    List<Type> argtypes;
    // The types of the actual method type arguments.
    List<Type> typeargtypes = null;
    Name methName = TreeInfo.name(tree.meth);
    boolean isConstructorCall = methName == names._this || methName == names._super;
    ListBuffer<Type> argtypesBuf = new ListBuffer<>();
    if (isConstructorCall) {
        // Check that this is the first statement in a constructor.
        if (checkFirstConstructorStat(tree, env)) {
            // Record the fact
            // that this is a constructor call (using isSelfCall).
            localEnv.info.isSelfCall = true;
            // Attribute arguments, yielding list of argument types.
            int kind = attribArgs(MTH, tree.args, localEnv, argtypesBuf);
            argtypes = argtypesBuf.toList();
            typeargtypes = attribTypes(tree.typeargs, localEnv);
            // Variable `site' points to the class in which the called
            // constructor is defined.
            Type site = env.enclClass.sym.type;
            if (methName == names._super) {
                if (site == syms.objectType) {
                    log.error(tree.meth.pos(), "no.superclass", site);
                    site = types.createErrorType(syms.objectType);
                } else {
                    site = types.supertype(site);
                }
            }
            if (site.hasTag(CLASS)) {
                Type encl = site.getEnclosingType();
                while (encl != null && encl.hasTag(TYPEVAR)) encl = encl.getUpperBound();
                if (encl.hasTag(CLASS)) {
                    if (tree.meth.hasTag(SELECT)) {
                        JCTree qualifier = ((JCFieldAccess) tree.meth).selected;
                        // We are seeing a prefixed call, of the form
                        // <expr>.super(...).
                        // Check that the prefix expression conforms
                        // to the outer instance type of the class.
                        chk.checkRefType(qualifier.pos(), attribExpr(qualifier, localEnv, encl));
                    } else if (methName == names._super) {
                        // qualifier omitted; check for existence
                        // of an appropriate implicit qualifier.
                        rs.resolveImplicitThis(tree.meth.pos(), localEnv, site, true);
                    }
                } else if (tree.meth.hasTag(SELECT)) {
                    log.error(tree.meth.pos(), "illegal.qual.not.icls", site.tsym);
                }
                // prefix the implicit String and int parameters
                if (site.tsym == syms.enumSym && allowEnums)
                    argtypes = argtypes.prepend(syms.intType).prepend(syms.stringType);
                // Resolve the called constructor under the assumption
                // that we are referring to a superclass instance of the
                // current instance (JLS ???).
                boolean selectSuperPrev = localEnv.info.selectSuper;
                localEnv.info.selectSuper = true;
                localEnv.info.pendingResolutionPhase = null;
                Symbol sym = rs.resolveConstructor(tree.meth.pos(), localEnv, site, argtypes, typeargtypes);
                localEnv.info.selectSuper = selectSuperPrev;
                // Set method symbol to resolved constructor...
                TreeInfo.setSymbol(tree.meth, sym);
                // ...and check that it is legal in the current context.
                // (this will also set the tree's type)
                Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes);
                checkId(tree.meth, site, sym, localEnv, new ResultInfo(kind, mpt));
            }
        // Otherwise, `site' is an error type and we do nothing
        }
        result = tree.type = syms.voidType;
    } else {
        // Otherwise, we are seeing a regular method call.
        // Attribute the arguments, yielding list of argument types, ...
        int kind = attribArgs(VAL, tree.args, localEnv, argtypesBuf);
        argtypes = argtypesBuf.toList();
        typeargtypes = attribAnyTypes(tree.typeargs, localEnv);
        // ... and attribute the method using as a prototype a methodtype
        // whose formal argument types is exactly the list of actual
        // arguments (this will also set the method symbol).
        Type mpt = newMethodTemplate(resultInfo.pt, argtypes, typeargtypes);
        localEnv.info.pendingResolutionPhase = null;
        Type mtype = attribTree(tree.meth, localEnv, new ResultInfo(kind, mpt, resultInfo.checkContext));
        // Compute the result type.
        Type restype = mtype.getReturnType();
        if (restype.hasTag(TypeTag.WILDCARD))
            throw new AssertionError(mtype);
        Type qualifier = (tree.meth.hasTag(SELECT)) ? ((JCFieldAccess) tree.meth).selected.type : env.enclClass.sym.type;
        restype = adjustMethodReturnType(qualifier, methName, argtypes, restype);
        chk.checkRefTypes(tree.typeargs, typeargtypes);
        // Check that value of resulting type is admissible in the
        // current context.  Also, capture the return type
        result = check(tree, capture(restype), VAL, resultInfo);
    }
    chk.validate(tree.typeargs, localEnv);
}
Also used : Symbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Type(org.eclipse.ceylon.langtools.tools.javac.code.Type)

Aggregations

JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)101 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)19 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)18 Symbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol)12 JCVariableDecl (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCVariableDecl)10 JCStatement (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCStatement)9 JavaFileObject (org.eclipse.ceylon.javax.tools.JavaFileObject)8 Type (org.eclipse.ceylon.langtools.tools.javac.code.Type)8 JCNewClass (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass)8 ListBuffer (org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer)8 SyntheticName (org.eclipse.ceylon.compiler.java.codegen.Naming.SyntheticName)7 Type (org.eclipse.ceylon.model.typechecker.model.Type)6 JCAnnotation (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAnnotation)5 JCBlock (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCBlock)4 JCClassDecl (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCClassDecl)4 JCCompilationUnit (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCCompilationUnit)4 JCPrimitiveTypeTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCPrimitiveTypeTree)4 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)4 IOException (java.io.IOException)3 TaskEvent (org.eclipse.ceylon.langtools.source.util.TaskEvent)3