⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transtypes.java

📁 是一款用JAVA 编写的编译器 具有很强的编译功能
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/* * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */package com.sun.tools.javac.comp;import java.util.*;import com.sun.tools.javac.code.*;import com.sun.tools.javac.code.Symbol.*;import com.sun.tools.javac.tree.*;import com.sun.tools.javac.tree.JCTree.*;import com.sun.tools.javac.util.*;import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;import com.sun.tools.javac.util.List;import static com.sun.tools.javac.code.Flags.*;import static com.sun.tools.javac.code.Kinds.*;import static com.sun.tools.javac.code.TypeTags.*;/** This pass translates Generic Java to conventional Java. * *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If *  you write code that depends on this, you do so at your own risk. *  This code and its internal interfaces are subject to change or *  deletion without notice.</b> */public class TransTypes extends TreeTranslator {    /** The context key for the TransTypes phase. */    protected static final Context.Key<TransTypes> transTypesKey =        new Context.Key<TransTypes>();    /** Get the instance for this context. */    public static TransTypes instance(Context context) {        TransTypes instance = context.get(transTypesKey);        if (instance == null)            instance = new TransTypes(context);        return instance;    }    private Name.Table names;    private Log log;    private Symtab syms;    private TreeMaker make;    private Enter enter;    private boolean allowEnums;    private Types types;    private final Resolve resolve;    /**     * Flag to indicate whether or not to generate bridge methods.     * For pre-Tiger source there is no need for bridge methods, so it     * can be skipped to get better performance for -source 1.4 etc.     */    private final boolean addBridges;    protected TransTypes(Context context) {        context.put(transTypesKey, this);        names = Name.Table.instance(context);        log = Log.instance(context);        syms = Symtab.instance(context);        enter = Enter.instance(context);        overridden = new HashMap<MethodSymbol,MethodSymbol>();        Source source = Source.instance(context);        allowEnums = source.allowEnums();        addBridges = source.addBridges();        types = Types.instance(context);        make = TreeMaker.instance(context);        resolve = Resolve.instance(context);    }    /** A hashtable mapping bridge methods to the methods they override after     *  type erasure.     */    Map<MethodSymbol,MethodSymbol> overridden;    /** Construct an attributed tree for a cast of expression to target type,     *  unless it already has precisely that type.     *  @param tree    The expression tree.     *  @param target  The target type.     */    JCExpression cast(JCExpression tree, Type target) {        int oldpos = make.pos;        make.at(tree.pos);        if (!types.isSameType(tree.type, target)) {            if (!resolve.isAccessible(env, target.tsym))                resolve.logAccessError(env, tree, target);            tree = make.TypeCast(make.Type(target), tree).setType(target);        }        make.pos = oldpos;        return tree;    }    /** Construct an attributed tree to coerce an expression to some erased     *  target type, unless the expression is already assignable to that type.     *  If target type is a constant type, use its base type instead.     *  @param tree    The expression tree.     *  @param target  The target type.     */    JCExpression coerce(JCExpression tree, Type target) {        Type btarget = target.baseType();        if (tree.type.isPrimitive() == target.isPrimitive()) {            return types.isAssignable(tree.type, btarget, Warner.noWarnings)                ? tree                : cast(tree, btarget);        }        return tree;    }    /** Given an erased reference type, assume this type as the tree's type.     *  Then, coerce to some given target type unless target type is null.     *  This operation is used in situations like the following:     *     *  class Cell<A> { A value; }     *  ...     *  Cell<Integer> cell;     *  Integer x = cell.value;     *     *  Since the erasure of Cell.value is Object, but the type     *  of cell.value in the assignment is Integer, we need to     *  adjust the original type of cell.value to Object, and insert     *  a cast to Integer. That is, the last assignment becomes:     *     *  Integer x = (Integer)cell.value;     *     *  @param tree       The expression tree whose type might need adjustment.     *  @param erasedType The expression's type after erasure.     *  @param target     The target type, which is usually the erasure of the     *                    expression's original type.     */    JCExpression retype(JCExpression tree, Type erasedType, Type target) {//      System.err.println("retype " + tree + " to " + erasedType);//DEBUG        if (erasedType.tag > lastBaseTag) {            if (target != null && target.isPrimitive())                target = erasure(tree.type);            tree.type = erasedType;            if (target != null) return coerce(tree, target);        }        return tree;    }    /** Translate method argument list, casting each argument     *  to its corresponding type in a list of target types.     *  @param _args            The method argument list.     *  @param parameters       The list of target types.     *  @param varargsElement   The erasure of the varargs element type,     *  or null if translating a non-varargs invocation     */    <T extends JCTree> List<T> translateArgs(List<T> _args,                                           List<Type> parameters,                                           Type varargsElement) {        if (parameters.isEmpty()) return _args;        List<T> args = _args;        while (parameters.tail.nonEmpty()) {            args.head = translate(args.head, parameters.head);            args = args.tail;            parameters = parameters.tail;        }        Type parameter = parameters.head;        assert varargsElement != null || args.length() == 1;        if (varargsElement != null) {            while (args.nonEmpty()) {                args.head = translate(args.head, varargsElement);                args = args.tail;            }        } else {            args.head = translate(args.head, parameter);        }        return _args;    }    /** Add a bridge definition and enter corresponding method symbol in     *  local scope of origin.     *     *  @param pos     The source code position to be used for the definition.     *  @param meth    The method for which a bridge needs to be added     *  @param impl    That method's implementation (possibly the method itself)     *  @param origin  The class to which the bridge will be added     *  @param hypothetical     *                 True if the bridge method is not strictly necessary in the     *                 binary, but is represented in the symbol table to detect     *                 erasure clashes.     *  @param bridges The list buffer to which the bridge will be added     */    void addBridge(DiagnosticPosition pos,                   MethodSymbol meth,                   MethodSymbol impl,                   ClassSymbol origin,                   boolean hypothetical,                   ListBuffer<JCTree> bridges) {        make.at(pos);        Type origType = types.memberType(origin.type, meth);        Type origErasure = erasure(origType);        // Create a bridge method symbol and a bridge definition without a body.        Type bridgeType = meth.erasure(types);        long flags = impl.flags() & AccessFlags | SYNTHETIC | BRIDGE;        if (hypothetical) flags |= HYPOTHETICAL;        MethodSymbol bridge = new MethodSymbol(flags,                                               meth.name,                                               bridgeType,                                               origin);        if (!hypothetical) {            JCMethodDecl md = make.MethodDef(bridge, null);            // The bridge calls this.impl(..), if we have an implementation            // in the current class, super.impl(...) otherwise.            JCExpression receiver = (impl.owner == origin)                ? make.This(origin.erasure(types))                : make.Super(types.supertype(origin.type).tsym.erasure(types), origin);            // The type returned from the original method.            Type calltype = erasure(impl.type.getReturnType());            // Construct a call of  this.impl(params), or super.impl(params),            // casting params and possibly results as needed.            JCExpression call =                make.Apply(                           null,                           make.Select(receiver, impl).setType(calltype),                           translateArgs(make.Idents(md.params), origErasure.getParameterTypes(), null))                .setType(calltype);            JCStatement stat = (origErasure.getReturnType().tag == VOID)                ? make.Exec(call)                : make.Return(coerce(call, bridgeType.getReturnType()));            md.body = make.Block(0, List.of(stat));            // Add bridge to `bridges' buffer            bridges.append(md);        }        // Add bridge to scope of enclosing class and `overridden' table.        origin.members().enter(bridge);        overridden.put(bridge, meth);    }    /** Add bridge if given symbol is a non-private, non-static member     *  of the given class, which is either defined in the class or non-final     *  inherited, and one of the two following conditions holds:     *  1. The method's type changes in the given class, as compared to the     *     class where the symbol was defined, (in this case     *     we have extended a parameterized class with non-trivial parameters).     *  2. The method has an implementation with a different erased return type.     *     (in this case we have used co-variant returns).

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -