summaryrefslogtreecommitdiff
path: root/sources/scala/tools/scalac/typechecker/Context.scala
blob: 822b4bf1489bf600f4152f8af060de43c1f25f47 (plain) (blame)
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
  }
}
}