1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
/* ____ ____ ____ ____ ______ *\
** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
** /_____/\____/\___/\____/____/ **
**
** $Id$
\* */
import scalac.{symtab => scalac_symtab}
import scalac.ast._;
import scalac.util.Names;
import scalac.util.Name;
package scala.tools.scalac.typechecker {
import scalac_symtab._;
object Context {
val NONE = new Context();
NONE.viewCache = List();
}
class Context {
import Kinds._;
var tree: Tree = _; // Tree associated with this context
var owner: Symbol = _; // The current owner
var scope: Scope = _; // The current scope
var outer: Context = _; // The next outer context
var enclClass: Context = this; // The next outer context whose tree
// is a class template
var prevImport: Context = this; // the next outer import context
var variance: int = _; // Variance relative to enclosing class.
var constructorClass: Symbol = _; // Class for auxiliary constructor
var viewCache: List[View] = null; // View symbols visible in scope
var infer: Infer = null; // Type inferencer
var depth: int = 0;
def this(tree: Tree, owner: Symbol, scope: Scope, outer: Context) = {
this();
this.tree = tree;
this.owner = owner;
this.scope = scope;
this.enclClass = if ((tree.isInstanceOf[Tree$Template] ||
tree.isInstanceOf[Tree$CompoundType]) &&
tree != outer.tree) this
else outer.enclClass;
this.prevImport = if (tree.isInstanceOf[Tree$Import] &&
tree != outer.tree) this
else outer.prevImport;
this.variance = outer.variance;
this.constructorClass = outer.constructorClass;
this.infer = outer.infer;
this.depth = outer.depth + 1;
this.outer = outer;
}
def this(tree: Tree, outer: Context) =
this(tree, outer.owner, outer.scope, outer);
def outerContext(clazz: Symbol): Context = {
var c = this;
while (c != Context.NONE && c.owner != clazz) c = c.outer.enclClass;
c
}
def isTopLevel(): boolean = tree match {
case Tree$Block(_,_) =>
false
case Tree$Template(_, _) =>
outer.tree.isInstanceOf[Tree$PackageDef]
case Tree.Empty =>
true
case _ =>
outer.isTopLevel()
}
def importString(): String =
if (prevImport == Context.NONE) ""
else
prevImport.outer.importString() +
prevImport.tree.symbol().toString() + ";";
def importPrefix(): Tree = tree match {
case Tree$Import(expr, _) => expr
}
def importType(): Type =
tree.symbol().getType();
def sameImport(that: Context): boolean =
this.importType().isSameAs(that.importType());
def importedSymbol(name: Name): Symbol = {
return TreeInfo.importedSymbol(tree, name);
}
def viewMeths: List[View] = {
def addView(sym: Symbol, symtype: Type, qual: Tree): unit = symtype match {
case Type$OverloadedType(alts, alttypes) =>
var i = alts.length - 1;
while (i >= 0) {
addView(alts(i), alttypes(i), qual);
i = i - 1;
}
case _ =>
/*
def isUnShadowed(view: View) =
view.context == this || !infer.specializes(view.symtype, symtype);
*/
if (viewCache.forall(v => v.sym != sym)) {
val v = View(sym, symtype, qual, this);
//System.out.println("VIEW " + sym + ":" + symtype + " " + qual);//DEBUG
viewCache = v :: viewCache;//.filter(isUnShadowed);
}
}
if (viewCache == null) {
viewCache = outer.viewMeths;
if (scope != outer.scope) {
val e = scope.lookupEntry(Names.view);
if (e.owner == scope && e.sym.kind == VAL)
addView(e.sym, e.sym.getType(), Tree.Empty);
}
if (prevImport == this) {
val sym = importedSymbol(Names.view);
if (sym.kind == VAL)
addView(sym, importType().memberType(sym), importPrefix());
}
}
viewCache
}
}
}
|