summaryrefslogtreecommitdiff
path: root/sources/scalac/transformer/matching/PatternNode.java
blob: cfa0d1b079fa01561d09ddececa71293eaa996b1 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
**                                                                      **
** $Id$
\*                                                                      */

package scalac.transformer.matching;

import scala.tools.util.Position;
import scalac.*;
import scalac.ast.*;
import scalac.atree.AConstant;
import scalac.symtab.*;
import scalac.typechecker.*;


/** Intermediate data structure for algebraic + pattern matcher
 */
public class PatternNode {
    public int pos = Position.FIRSTPOS;
    public Type type;
    public PatternNode or;
    public PatternNode and;

    public case Header(Tree selector, Header next) ;
    public case Body(Tree.ValDef[][] bound, Tree[] guard, Tree[] body);
    public case DefaultPat();
    public case ConstrPat(Symbol casted);
    public case ConstantPat(AConstant value);
    public case VariablePat(Tree tree);
    public case AltPat(Header subheader);
    public case SequencePat(Symbol casted, int len); // only used in PatternMatcher
    public case SeqContainerPat(Symbol casted, Tree seqpat); //   in AlgebraicMatcher

    public PatternNode dup() {
    	PatternNode res;
    	switch (this) {
			case Header(Tree selector, Header next):
				res = Header(selector, next);
				break;
			case Body(Tree.ValDef[][] bound, Tree[] guard, Tree[] body):
				res = Body(bound, guard, body);
				break;
			case DefaultPat():
				res = DefaultPat();
				break;
			case ConstrPat(Symbol casted):
				res = ConstrPat(casted);
				break;
			case SequencePat(Symbol casted, int len):
				res = SequencePat(casted, len);
				break;
			case SeqContainerPat(Symbol casted, Tree seqpat):
				res = SeqContainerPat(casted, seqpat);
				break;
			case ConstantPat(AConstant value):
				res = ConstantPat(value);
				break;
			case VariablePat(Tree tree):
				res = VariablePat(tree);
				break;
			case AltPat(Header subheader):
				res = AltPat(subheader);
				break;
			default:
				throw new ApplicationError();
    	}
    	res.pos = pos;
   		res.type = type;
   		res.or = or;
   		res.and = and;
   		return res;
    }

    public Symbol symbol() {
        switch (this) {
            case ConstrPat(Symbol casted):
                return casted;
            case SequencePat(Symbol casted, _):
                return casted;
            case SeqContainerPat(Symbol casted, _):
                return casted;
            default:
                return Symbol.NONE;
        }
    }

    public PatternNode next() {
    	switch (this) {
    		case Header(_, Header next):
    			return next;
    		default:
    			return null;
    	}
    }

    public final boolean isDefaultPat() {
        switch( this ) {
        case DefaultPat():
            return true;
        default:
            return false;
        }
    }

    /** returns true if
     *  p and q are equal (constructor | sequence) type tests, or
     *  "q matches" => "p matches"
     */
    public final boolean isSameAs( PatternNode q ) {
        switch( this ) {
        case ConstrPat(_):
            switch (q) {
            case ConstrPat(_):
                return q.type.isSameAs( this.type );
            }
            return false;
        case SequencePat(_, int plen):
            switch (q) {
            case SequencePat(_, int qlen):
                return (plen == qlen) && q.type.isSameAs( this.type );
            }
            return false;
        default:
            return subsumes( q );
        }
    }

    /** returns true if "q matches" => "p matches"
     */
    public final boolean subsumes( PatternNode q ) {
        switch (this) {
        case DefaultPat():
            switch (q) {
            case DefaultPat():
                return true;
            }
            return false;
        case ConstrPat(_):
            switch (q) {
            case ConstrPat(_):
                return q.type.isSubType(this.type);
            }
            return false;
        case SequencePat(_, int plen):
            switch (q) {
            case SequencePat(_, int qlen):
                return (plen == qlen) && q.type.isSubType(this.type);
            }
            return false;
        case ConstantPat(AConstant pval):
            switch (q) {
            case ConstantPat(AConstant qval):
                return pval.equals(qval);
            }
            return false;
        case VariablePat(Tree tree):
            switch (q) {
            case VariablePat(Tree other):
                return (tree.symbol() != null) &&
                    (tree.symbol().kind != Kinds.NONE) &&
                    (tree.symbol().kind != Kinds.ERROR) &&
                    (tree.symbol() == other.symbol());
            }
            return false;
        }
        return false;
    }

    public String toString() {
        switch (this) {
            case Header(Tree selector, Header next):
                return "Header(" + selector + ")";
            case Body( _, _, _ ):
                return "Body";
            case DefaultPat():
                return "DefaultPat";
            case ConstrPat(Symbol casted):
                return "ConstrPat(" + casted + ")";
            case SequencePat(Symbol casted, int len):
                return "SequencePat(" + casted + ", " + len + "...)";
            case SeqContainerPat(Symbol casted, Tree seqpat):
                return "SeqContainerPat(" + casted + ", " + seqpat + ")";
            case ConstantPat(AConstant value):
                return "ConstantPat(" + value + ")";
            case VariablePat(Tree tree):
                return "VariablePat";
            default:
                return "<unknown pat>";
        }
    }
}