Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.javac.comp;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.comp.Attr.ResultInfo;
import com.sun.tools.javac.comp.Infer.InferenceContext;
import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
import com.sun.tools.javac.comp.Resolve.ReferenceLookupHelper;
import com.sun.tools.javac.tree.JCTree.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import static com.sun.tools.javac.code.TypeTag.*;
import static com.sun.tools.javac.tree.JCTree.Tag.*;
/**
* This is an helper class that is used to perform deferred type-analysis.
* Each time a poly expression occurs in argument position, javac attributes it
* with a temporary 'deferred type' that is checked (possibly multiple times)
* against an expected formal type.
*
*
This is NOT part of any supported API.
* 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.
*/
public class DeferredAttr extends JCTree.Visitor {
protected static final Context.Key deferredAttrKey =
new Context.Key();
final Attr attr;
final Check chk;
final JCDiagnostic.Factory diags;
final Enter enter;
final Infer infer;
final Resolve rs;
final Log log;
final Symtab syms;
final TreeMaker make;
final Types types;
public static DeferredAttr instance(Context context) {
DeferredAttr instance = context.get(deferredAttrKey);
if (instance == null)
instance = new DeferredAttr(context);
return instance;
}
protected DeferredAttr(Context context) {
context.put(deferredAttrKey, this);
attr = Attr.instance(context);
chk = Check.instance(context);
diags = JCDiagnostic.Factory.instance(context);
enter = Enter.instance(context);
infer = Infer.instance(context);
rs = Resolve.instance(context);
log = Log.instance(context);
syms = Symtab.instance(context);
make = TreeMaker.instance(context);
types = Types.instance(context);
Names names = Names.instance(context);
stuckTree = make.Ident(names.empty).setType(Type.stuckType);
emptyDeferredAttrContext =
new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) {
@Override
void addDeferredAttrNode(DeferredType dt, ResultInfo ri, DeferredStuckPolicy deferredStuckPolicy) {
Assert.error("Empty deferred context!");
}
@Override
void complete() {
Assert.error("Empty deferred context!");
}
};
}
/** shared tree for stuck expressions */
final JCTree stuckTree;
/**
* This type represents a deferred type. A deferred type starts off with
* no information on the underlying expression type. Such info needs to be
* discovered through type-checking the deferred type against a target-type.
* Every deferred type keeps a pointer to the AST node from which it originated.
*/
public class DeferredType extends Type {
public JCExpression tree;
Env env;
AttrMode mode;
SpeculativeCache speculativeCache;
DeferredType(JCExpression tree, Env env) {
super(null);
this.tree = tree;
this.env = attr.copyEnv(env);
this.speculativeCache = new SpeculativeCache();
}
@Override
public TypeTag getTag() {
return DEFERRED;
}
/**
* A speculative cache is used to keep track of all overload resolution rounds
* that triggered speculative attribution on a given deferred type. Each entry
* stores a pointer to the speculative tree and the resolution phase in which the entry
* has been added.
*/
class SpeculativeCache {
private Map> cache =
new WeakHashMap>();
class Entry {
JCTree speculativeTree;
ResultInfo resultInfo;
public Entry(JCTree speculativeTree, ResultInfo resultInfo) {
this.speculativeTree = speculativeTree;
this.resultInfo = resultInfo;
}
boolean matches(MethodResolutionPhase phase) {
return resultInfo.checkContext.deferredAttrContext().phase == phase;
}
}
/**
* Retrieve a speculative cache entry corresponding to given symbol
* and resolution phase
*/
Entry get(Symbol msym, MethodResolutionPhase phase) {
List entries = cache.get(msym);
if (entries == null) return null;
for (Entry e : entries) {
if (e.matches(phase)) return e;
}
return null;
}
/**
* Stores a speculative cache entry corresponding to given symbol
* and resolution phase
*/
void put(JCTree speculativeTree, ResultInfo resultInfo) {
Symbol msym = resultInfo.checkContext.deferredAttrContext().msym;
List entries = cache.get(msym);
if (entries == null) {
entries = List.nil();
}
cache.put(msym, entries.prepend(new Entry(speculativeTree, resultInfo)));
}
}
/**
* Get the type that has been computed during a speculative attribution round
*/
Type speculativeType(Symbol msym, MethodResolutionPhase phase) {
SpeculativeCache.Entry e = speculativeCache.get(msym, phase);
return e != null ? e.speculativeTree.type : Type.noType;
}
/**
* Check a deferred type against a potential target-type. Depending on
* the current attribution mode, a normal vs. speculative attribution
* round is performed on the underlying AST node. There can be only one
* speculative round for a given target method symbol; moreover, a normal
* attribution round must follow one or more speculative rounds.
*/
Type check(ResultInfo resultInfo) {
DeferredStuckPolicy deferredStuckPolicy;
if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
deferredStuckPolicy = dummyStuckPolicy;
} else if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.SPECULATIVE) {
deferredStuckPolicy = new OverloadStuckPolicy(resultInfo, this);
} else {
deferredStuckPolicy = new CheckStuckPolicy(resultInfo, this);
}
return check(resultInfo, deferredStuckPolicy, basicCompleter);
}
private Type check(ResultInfo resultInfo, DeferredStuckPolicy deferredStuckPolicy,
DeferredTypeCompleter deferredTypeCompleter) {
DeferredAttrContext deferredAttrContext =
resultInfo.checkContext.deferredAttrContext();
Assert.check(deferredAttrContext != emptyDeferredAttrContext);
if (deferredStuckPolicy.isStuck()) {
deferredAttrContext.addDeferredAttrNode(this, resultInfo, deferredStuckPolicy);
return Type.noType;
} else {
try {
return deferredTypeCompleter.complete(this, resultInfo, deferredAttrContext);
} finally {
mode = deferredAttrContext.mode;
}
}
}
}
/**
* A completer for deferred types. Defines an entry point for type-checking
* a deferred type.
*/
interface DeferredTypeCompleter {
/**
* Entry point for type-checking a deferred type. Depending on the
* circumstances, type-checking could amount to full attribution
* or partial structural check (aka potential applicability).
*/
Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext);
}
/**
* A basic completer for deferred types. This completer type-checks a deferred type
* using attribution; depending on the attribution mode, this could be either standard
* or speculative attribution.
*/
DeferredTypeCompleter basicCompleter = new DeferredTypeCompleter() {
public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
switch (deferredAttrContext.mode) {
case SPECULATIVE:
//Note: if a symbol is imported twice we might do two identical
//speculative rounds...
Assert.check(dt.mode == null || dt.mode == AttrMode.SPECULATIVE);
JCTree speculativeTree = attribSpeculative(dt.tree, dt.env, resultInfo);
dt.speculativeCache.put(speculativeTree, resultInfo);
return speculativeTree.type;
case CHECK:
Assert.check(dt.mode != null);
return attr.attribTree(dt.tree, dt.env, resultInfo);
}
Assert.error();
return null;
}
};
DeferredTypeCompleter dummyCompleter = new DeferredTypeCompleter() {
public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
Assert.check(deferredAttrContext.mode == AttrMode.CHECK);
return dt.tree.type = Type.stuckType;
}
};
/**
* Policy for detecting stuck expressions. Different criteria might cause
* an expression to be judged as stuck, depending on whether the check
* is performed during overload resolution or after most specific.
*/
interface DeferredStuckPolicy {
/**
* Has the policy detected that a given expression should be considered stuck?
*/
boolean isStuck();
/**
* Get the set of inference variables a given expression depends upon.
*/
Set stuckVars();
/**
* Get the set of inference variables which might get new constraints
* if a given expression is being type-checked.
*/
Set depVars();
}
/**
* Basic stuck policy; an expression is never considered to be stuck.
*/
DeferredStuckPolicy dummyStuckPolicy = new DeferredStuckPolicy() {
@Override
public boolean isStuck() {
return false;
}
@Override
public Set stuckVars() {
return Collections.emptySet();
}
@Override
public Set depVars() {
return Collections.emptySet();
}
};
/**
* The 'mode' in which the deferred type is to be type-checked
*/
public enum AttrMode {
/**
* A speculative type-checking round is used during overload resolution
* mainly to generate constraints on inference variables. Side-effects
* arising from type-checking the expression associated with the deferred
* type are reversed after the speculative round finishes. This means the
* expression tree will be left in a blank state.
*/
SPECULATIVE,
/**
* This is the plain type-checking mode. Produces side-effects on the underlying AST node
*/
CHECK;
}
/**
* Routine that performs speculative type-checking; the input AST node is
* cloned (to avoid side-effects cause by Attr) and compiler state is
* restored after type-checking. All diagnostics (but critical ones) are
* disabled during speculative type-checking.
*/
JCTree attribSpeculative(JCTree tree, Env env, ResultInfo resultInfo) {
final JCTree newTree = new TreeCopier