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
|
/* NSC -- new Scala compiler
* Copyright 2005-2009 LAMP/EPFL
* @author Martin Odersky
*/
// $Id$
package scala.tools.nsc
package backend
package icode
/** This trait ...
*
* @author Iulian Dragos
* @version 1.0
*/
trait TypeStacks { self: ICodes =>
import opcodes._
import global.{Symbol, Type, definitions}
/* This class simulates the type of the opperand
* stack of the ICode.
*/
type Rep = List[TypeKind]
class TypeStack {
var types: Rep = Nil
def this(stack: Rep) = {
this()
this.types = stack
}
def this(that: TypeStack) = this(that.types)
def length: Int = types.length
/** Push a type on the type stack. UNITs are ignored. */
def push(t: TypeKind) =
if (t != UNIT)
types = t :: types
def head: TypeKind = types.head
/** Removes the value on top of the stack, and returns it. It assumes
* the stack contains at least one element.
*/
def pop: TypeKind = {
val t = types.head
types = types.tail
t
}
/** Return the topmost two values on the stack. It assumes the stack
* is large enough. Topmost element first.
*/
def pop2: (TypeKind, TypeKind) = (pop, pop)
/** Return the topmost three values on the stack. It assumes the stack
* is large enough. Topmost element first.
*/
def pop3: (TypeKind, TypeKind, TypeKind) = (pop, pop, pop)
/** Drop the first n elements of the stack. */
def pop(n: Int): List[TypeKind] = {
val prefix = types.take(n)
types = types.drop(n)
prefix
}
def apply(n: Int): TypeKind = types(n)
/**
* A TypeStack aggress with another one if they have the same
* length and each type kind agrees position-wise. Two
* types agree if one is a subtype of the other.
*/
def agreesWith(other: TypeStack): Boolean =
(types.length == other.types.length) &&
List.forall2(types, other.types) ((t1, t2) => t1 <:< t2 || t2 <:< t1)
def mergeWith(that: TypeStack): TypeStack = {
def merge(a: TypeStack, b: TypeStack): TypeStack = {
val lst = List.map2(a.types, b.types) ((k1, k2) => k1 match {
case REFERENCE(cls1) =>
val REFERENCE(cls2) = k2
lub(k1,k2)
case _ => k1
})
new TypeStack(lst)
}
assert(this agreesWith that,
"Incompatible type stacks: " + this + ", " + that)
merge(this, that)
}
/* This method returns a String representation of the stack */
override def toString() = types.mkString("<", ",", ">")
override def equals(other: Any): Boolean =
other.isInstanceOf[TypeStack] &&
List.forall2(other.asInstanceOf[TypeStack].types, types)((a, b) => a == b)
}
}
|