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
|
package dotty.tools.dotc.core
import Types._, Names._, Flags._, Positions._
object Trees {
abstract class Modifiers {
val flags: FlagSet
}
class MissingType {
type Type
}
val missing: MissingType =
new MissingType {
type Type = Types.Type
}
/** Trees take a parameter indicating what the type of their `tpe` field
* is. Two choices: `Types.Type` or `missing.Type`.
* Untyped trees have type `Tree[missing.Type]`. Because `missing.Type`
* is a completely abstract type, there's nothing one can do with it.
*
* Tree typing uses a copy-on-write implementation:
*
* - You can never observe a `tpe` which is `null` (throws an exception)
* - So when creating a typed tree with `withType` we can re-use
* the existing tree transparently, assigning its `tpe` field,
* provided it was `null` before.
* - It is impossible to embed untyped trees in typed ones.
* - It is possible to embed typed trees in untyped ones. In fact
* there is an implicit conversion from `Tree[Types.Type]` to
* `Tree[missing.Type]` which wraps the typed tree in a
* `TypedSplice` node.
* - Type checking an untyped tree will remove all embedded `TypedSplice`
* nodes.
*/
abstract class Tree[T] {
def pos: Position
private var _tpe: T = _
def tpe: T = {
if (_tpe == null) throw new UnAssignedTypeException(this)
_tpe
}
def withType(tpe: Type): Tree[Type] = {
val tree =
(if (_tpe == null ||
(_tpe.asInstanceOf[AnyRef] eq tpe.asInstanceOf[AnyRef])) this
else shallowCopy).asInstanceOf[Tree[Type]]
tree._tpe = tpe
tree
}
def shallowCopy: Tree[T] = clone.asInstanceOf[Tree[T]]
}
case class Ident[T](name: Name)(implicit val pos: Position) extends Tree[T]
case class Select[T](qualifier: Tree[T], name: Name)(implicit val pos: Position) extends Tree[T]
case class Apply[T](fun: Tree[T], arg: Tree[T])(implicit val pos: Position) extends Tree[T]
case class Pair[T](left: Tree[T], right: Tree[T])(implicit val pos: Position) extends Tree[T]
case class ValDef[T](mods: Modifiers, name: Name, rtpe: Tree[T], rhs: Tree[T])(implicit val pos: Position) extends Tree[T]
case class TypeDef[T](mods: Modifiers, name: Name, rhs: Tree[T])(implicit val pos: Position) extends Tree[T]
case class DefDef[T](mods: Modifiers, name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], rtpe: Tree[T], rhs: Tree[T])(implicit val pos: Position) extends Tree[T]
case class TypedSplice(tree: Tree[Type]) extends Tree[missing.Type] {
def pos = tree.pos
}
implicit def embedTyped(tree: Tree[Type]): Tree[missing.Type] = TypedSplice(tree)
class UnAssignedTypeException[T](tree: Tree[T]) extends Exception {
override def getMessage: String = s"type of $tree is not assigned"
}
}
|