Search in sources :

Example 6 with Symbol

use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.

the class Lower method makeOwnerThisN.

/**
 * Similar to makeOwnerThis but will never pick "this".
 */
JCExpression makeOwnerThisN(DiagnosticPosition pos, Symbol sym, boolean preciseMatch) {
    Symbol c = sym.owner;
    List<VarSymbol> ots = outerThisStack;
    if (ots.isEmpty()) {
        log.error(pos, "no.encl.instance.of.type.in.scope", c);
        Assert.error();
        return makeNull();
    }
    VarSymbol ot = ots.head;
    JCExpression tree = access(make.at(pos).Ident(ot));
    TypeSymbol otc = ot.type.tsym;
    while (!(preciseMatch ? sym.isMemberOf(otc, types) : otc.isSubClass(sym.owner, types))) {
        do {
            ots = ots.tail;
            if (ots.isEmpty()) {
                log.error(pos, "no.encl.instance.of.type.in.scope", c);
                Assert.error();
                return tree;
            }
            ot = ots.head;
        } while (ot.owner != otc);
        tree = access(make.at(pos).Select(tree, ot));
        otc = ot.type.tsym;
    }
    return tree;
}
Also used : Symbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol)

Example 7 with Symbol

use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.

the class Lower method classOfType.

private JCExpression classOfType(Type type, DiagnosticPosition pos) {
    switch(type.getTag()) {
        case BYTE:
        case SHORT:
        case CHAR:
        case INT:
        case LONG:
        case FLOAT:
        case DOUBLE:
        case BOOLEAN:
        case VOID:
            // replace with <BoxedClass>.TYPE
            ClassSymbol c = types.boxedClass(type);
            Symbol typeSym = rs.accessBase(rs.findIdentInType(attrEnv, c.type, names.TYPE, VAR), pos, c.type, names.TYPE, true);
            if (typeSym.kind == VAR)
                // ensure initializer is evaluated
                ((VarSymbol) typeSym).getConstValue();
            return make.QualIdent(typeSym);
        case CLASS:
        case ARRAY:
            if (target.hasClassLiterals()) {
                VarSymbol sym = new VarSymbol(STATIC | PUBLIC | FINAL, names._class, syms.classType, type.tsym);
                return make_at(pos).Select(make.Type(type), sym);
            }
            // replace with <cache == null ? cache = class$(tsig) : cache>
            // where
            // - <tsig>  is the type signature of T,
            // - <cache> is the cache variable for tsig.
            String sig = writer.xClassName(type).toString().replace('/', '.');
            Symbol cs = cacheSym(pos, sig);
            return make_at(pos).Conditional(makeBinary(EQ, make.Ident(cs), makeNull()), make.Assign(make.Ident(cs), make.App(make.Ident(classDollarSym(pos)), List.<JCExpression>of(make.Literal(CLASS, sig).setType(syms.stringType)))).setType(types.erasure(syms.classType)), make.Ident(cs)).setType(types.erasure(syms.classType));
        default:
            throw new AssertionError();
    }
}
Also used : Symbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol)

Example 8 with Symbol

use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.

the class Lower method access.

/**
 * Ensure that identifier is accessible, return tree accessing the identifier.
 *  @param sym      The accessed symbol.
 *  @param tree     The tree referring to the symbol.
 *  @param enclOp   The closest enclosing operation node of tree,
 *                  null if tree is not a subtree of an operation.
 *  @param refSuper Is access via a (qualified) C.super?
 */
JCExpression access(Symbol sym, JCExpression tree, JCExpression enclOp, boolean refSuper) {
    // Access a free variable via its proxy, or its proxy's proxy
    while (sym.kind == VAR && sym.owner.kind == MTH && sym.owner.enclClass() != currentClass) {
        // A constant is replaced by its constant value.
        Object cv = ((VarSymbol) sym).getConstValue();
        if (cv != null) {
            make.at(tree.pos);
            return makeLit(sym.type, cv);
        }
        // Otherwise replace the variable by its proxy.
        sym = proxies.lookup(proxyName(sym.name)).sym;
        Assert.check(sym != null && (sym.flags_field & FINAL) != 0);
        tree = make.at(tree.pos).Ident(sym);
    }
    JCExpression base = (tree.hasTag(SELECT)) ? ((JCFieldAccess) tree).selected : null;
    switch(sym.kind) {
        case TYP:
            if (sym.owner.kind != PCK) {
                // Convert type idents to
                // <flat name> or <package name> . <flat name>
                Name flatname = Convert.shortName(sym.flatName());
                while (base != null && TreeInfo.symbol(base) != null && TreeInfo.symbol(base).kind != PCK) {
                    base = (base.hasTag(SELECT)) ? ((JCFieldAccess) base).selected : null;
                }
                if (tree.hasTag(IDENT)) {
                    ((JCIdent) tree).name = flatname;
                } else if (base == null) {
                    tree = make.at(tree.pos).Ident(sym);
                    ((JCIdent) tree).name = flatname;
                } else {
                    ((JCFieldAccess) tree).selected = base;
                    ((JCFieldAccess) tree).name = flatname;
                }
            }
            break;
        case MTH:
        case VAR:
            if (sym.owner.kind == TYP) {
                // Access methods are required for
                // - private members,
                // - protected members in a superclass of an
                // enclosing class contained in another package.
                // - all non-private members accessed via a qualified super.
                boolean protAccess = refSuper && !needsPrivateAccess(sym) || needsProtectedAccess(sym, tree);
                boolean accReq = protAccess || needsPrivateAccess(sym);
                // A base has to be supplied for
                // - simple identifiers accessing variables in outer classes.
                boolean baseReq = base == null && sym.owner != syms.predefClass && !sym.isMemberOf(currentClass, types);
                if (accReq || baseReq) {
                    make.at(tree.pos);
                    // Constants are replaced by their constant value.
                    if (sym.kind == VAR) {
                        Object cv = ((VarSymbol) sym).getConstValue();
                        if (cv != null) {
                            addPrunedInfo(tree);
                            return makeLit(sym.type, cv);
                        }
                    }
                    // to their access methods.
                    if (accReq) {
                        List<JCExpression> args = List.nil();
                        if ((sym.flags() & STATIC) == 0) {
                            // as first parameter.
                            if (base == null)
                                base = makeOwnerThis(tree.pos(), sym, true);
                            args = args.prepend(base);
                            // so we don't duplicate code
                            base = null;
                        }
                        Symbol access = accessSymbol(sym, tree, enclOp, protAccess, refSuper);
                        JCExpression receiver = make.Select(base != null ? base : make.QualIdent(access.owner), access);
                        return make.App(receiver, args);
                    // Other accesses to members of outer classes get a
                    // qualifier.
                    } else if (baseReq) {
                        return make.at(tree.pos).Select(accessBase(tree.pos(), sym), sym).setType(tree.type);
                    }
                }
            } else if (sym.owner.kind == MTH && lambdaTranslationMap != null) {
                // sym is a local variable - check the lambda translation map to
                // see if sym has been translated to something else in the current
                // scope (by LambdaToMethod)
                Symbol translatedSym = lambdaTranslationMap.get(sym);
                if (translatedSym != null) {
                    tree = make.at(tree.pos).Ident(translatedSym);
                }
            }
    }
    return tree;
}
Also used : Symbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol)

Example 9 with Symbol

use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.

the class Lower method visitEnumDef.

/**
 * Translate an enum class.
 */
private void visitEnumDef(JCClassDecl tree) {
    make_at(tree.pos());
    // add the supertype, if needed
    if (tree.extending == null)
        tree.extending = make.Type(types.supertype(tree.type));
    // classOfType adds a cache field to tree.defs unless
    // target.hasClassLiterals().
    JCExpression e_class = classOfType(tree.sym.type, tree.pos()).setType(types.erasure(syms.classType));
    // process each enumeration constant, adding implicit constructor parameters
    int nextOrdinal = 0;
    ListBuffer<JCExpression> values = new ListBuffer<JCExpression>();
    ListBuffer<JCTree> enumDefs = new ListBuffer<JCTree>();
    ListBuffer<JCTree> otherDefs = new ListBuffer<JCTree>();
    for (List<JCTree> defs = tree.defs; defs.nonEmpty(); defs = defs.tail) {
        if (defs.head.hasTag(VARDEF) && (((JCVariableDecl) defs.head).mods.flags & ENUM) != 0) {
            JCVariableDecl var = (JCVariableDecl) defs.head;
            visitEnumConstantDef(var, nextOrdinal++);
            values.append(make.QualIdent(var.sym));
            enumDefs.append(var);
        } else {
            otherDefs.append(defs.head);
        }
    }
    // private static final T[] #VALUES = { a, b, c };
    Name valuesName = names.fromString(target.syntheticNameChar() + "VALUES");
    while (// avoid name clash
    tree.sym.members().lookup(valuesName).scope != null) valuesName = names.fromString(valuesName + "" + target.syntheticNameChar());
    Type arrayType = new ArrayType(types.erasure(tree.type), syms.arrayClass);
    VarSymbol valuesVar = new VarSymbol(PRIVATE | FINAL | STATIC | SYNTHETIC, valuesName, arrayType, tree.type.tsym);
    JCNewArray newArray = make.NewArray(make.Type(types.erasure(tree.type)), List.<JCExpression>nil(), values.toList());
    newArray.type = arrayType;
    enumDefs.append(make.VarDef(valuesVar, newArray));
    tree.sym.members().enter(valuesVar);
    Symbol valuesSym = lookupMethod(tree.pos(), names.values, tree.type, List.<Type>nil());
    List<JCStatement> valuesBody;
    if (useClone()) {
        // return (T[]) $VALUES.clone();
        JCTypeCast valuesResult = make.TypeCast(valuesSym.type.getReturnType(), make.App(make.Select(make.Ident(valuesVar), syms.arrayCloneMethod)));
        valuesBody = List.<JCStatement>of(make.Return(valuesResult));
    } else {
        // template: T[] $result = new T[$values.length];
        Name resultName = names.fromString(target.syntheticNameChar() + "result");
        while (// avoid name clash
        tree.sym.members().lookup(resultName).scope != null) resultName = names.fromString(resultName + "" + target.syntheticNameChar());
        VarSymbol resultVar = new VarSymbol(FINAL | SYNTHETIC, resultName, arrayType, valuesSym);
        JCNewArray resultArray = make.NewArray(make.Type(types.erasure(tree.type)), List.of(make.Select(make.Ident(valuesVar), syms.lengthVar)), null);
        resultArray.type = arrayType;
        JCVariableDecl decl = make.VarDef(resultVar, resultArray);
        // template: System.arraycopy($VALUES, 0, $result, 0, $VALUES.length);
        if (systemArraycopyMethod == null) {
            systemArraycopyMethod = new MethodSymbol(PUBLIC | STATIC, names.fromString("arraycopy"), new MethodType(List.<Type>of(syms.objectType, syms.intType, syms.objectType, syms.intType, syms.intType), syms.voidType, List.<Type>nil(), syms.methodClass), syms.systemType.tsym);
        }
        JCStatement copy = make.Exec(make.App(make.Select(make.Ident(syms.systemType.tsym), systemArraycopyMethod), List.of(make.Ident(valuesVar), make.Literal(0), make.Ident(resultVar), make.Literal(0), make.Select(make.Ident(valuesVar), syms.lengthVar))));
        // template: return $result;
        JCStatement ret = make.Return(make.Ident(resultVar));
        valuesBody = List.<JCStatement>of(decl, copy, ret);
    }
    JCMethodDecl valuesDef = make.MethodDef((MethodSymbol) valuesSym, make.Block(0, valuesBody));
    enumDefs.append(valuesDef);
    if (debugLower)
        System.err.println(tree.sym + ".valuesDef = " + valuesDef);
    /**
     * The template for the following code is:
     *
     *     public static E valueOf(String name) {
     *         return (E)Enum.valueOf(E.class, name);
     *     }
     *
     *  where E is tree.sym
     */
    MethodSymbol valueOfSym = lookupMethod(tree.pos(), names.valueOf, tree.sym.type, List.of(syms.stringType));
    Assert.check((valueOfSym.flags() & STATIC) != 0);
    VarSymbol nameArgSym = valueOfSym.params.head;
    JCIdent nameVal = make.Ident(nameArgSym);
    JCStatement enum_ValueOf = make.Return(make.TypeCast(tree.sym.type, makeCall(make.Ident(syms.enumSym), names.valueOf, List.of(e_class, nameVal))));
    JCMethodDecl valueOf = make.MethodDef(valueOfSym, make.Block(0, List.of(enum_ValueOf)));
    nameVal.sym = valueOf.params.head.sym;
    if (debugLower)
        System.err.println(tree.sym + ".valueOf = " + valueOf);
    enumDefs.append(valueOf);
    enumDefs.appendList(otherDefs.toList());
    tree.defs = enumDefs.toList();
}
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)

Example 10 with Symbol

use of org.eclipse.ceylon.langtools.tools.javac.code.Symbol in project ceylon by eclipse.

the class Lower method visitNewClass.

public void visitNewClass(JCNewClass tree) {
    ClassSymbol c = (ClassSymbol) tree.constructor.owner;
    // Box arguments, if necessary
    boolean isEnum = (tree.constructor.owner.flags() & ENUM) != 0;
    List<Type> argTypes = tree.constructor.type.getParameterTypes();
    if (isEnum)
        argTypes = argTypes.prepend(syms.intType).prepend(syms.stringType);
    tree.args = boxArgs(argTypes, tree.args, tree.varargsElement);
    tree.varargsElement = null;
    // explicit constructor arguments.
    if (c.isLocal()) {
        tree.args = tree.args.appendList(loadFreevars(tree.pos(), freevars(c)));
    }
    // If an access constructor is used, append null as a last argument.
    Symbol constructor = accessConstructor(tree.pos(), tree.constructor);
    if (constructor != tree.constructor) {
        tree.args = tree.args.append(makeNull());
        tree.constructor = constructor;
    }
    // correct outer instance as first argument.
    if (c.hasOuterInstance()) {
        JCExpression thisArg;
        if (tree.encl != null) {
            thisArg = attr.makeNullCheck(translate(tree.encl));
            thisArg.type = tree.encl.type;
        } else if (c.isLocal()) {
            // local class
            thisArg = makeThis(tree.pos(), c.type.getEnclosingType().tsym);
        } else {
            // nested class
            thisArg = makeOwnerThis(tree.pos(), c, false);
        }
        tree.args = tree.args.prepend(thisArg);
    }
    tree.encl = null;
    // than the class or interface following new.
    if (tree.def != null) {
        translate(tree.def);
        tree.clazz = access(make_at(tree.clazz.pos()).Ident(tree.def.sym));
        tree.def = null;
    } else {
        tree.clazz = access(c, tree.clazz, enclOp, false);
    }
    result = tree;
}
Also used : Type(org.eclipse.ceylon.langtools.tools.javac.code.Type) Symbol(org.eclipse.ceylon.langtools.tools.javac.code.Symbol)

Aggregations

Symbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol)115 Type (org.eclipse.ceylon.langtools.tools.javac.code.Type)42 ClassSymbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol.ClassSymbol)16 MethodSymbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol.MethodSymbol)15 VarSymbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol.VarSymbol)12 TypeSymbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol.TypeSymbol)11 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)11 DeferredAttrContext (org.eclipse.ceylon.langtools.tools.javac.comp.DeferredAttr.DeferredAttrContext)8 DeferredType (org.eclipse.ceylon.langtools.tools.javac.comp.DeferredAttr.DeferredType)8 DiagnosticType (org.eclipse.ceylon.langtools.tools.javac.util.JCDiagnostic.DiagnosticType)8 DynamicMethodSymbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol.DynamicMethodSymbol)6 MethodType (org.eclipse.ceylon.langtools.tools.javac.code.Type.MethodType)6 JavaFileObject (org.eclipse.ceylon.javax.tools.JavaFileObject)5 DiagnosticPosition (org.eclipse.ceylon.langtools.tools.javac.util.JCDiagnostic.DiagnosticPosition)4 ErrorType (org.eclipse.ceylon.javax.lang.model.type.ErrorType)3 Scope (org.eclipse.ceylon.langtools.tools.javac.code.Scope)3 PackageSymbol (org.eclipse.ceylon.langtools.tools.javac.code.Symbol.PackageSymbol)3 HashSet (java.util.HashSet)2 LinkedList (java.util.LinkedList)2 DeclaredType (org.eclipse.ceylon.javax.lang.model.type.DeclaredType)2