summaryrefslogtreecommitdiff
path: root/sources/scalac/util/Name.java
blob: 96d674e5c45d644f3a38eaaaaf33167b53ee2471 (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
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
**                                                                      **
** $Id$
\*                                                                      */

package scalac.util;

import java.util.HashMap;

public final class Name {

/** address in the name memory
 */
    public final int index;

    private final String string;

/** hashtable for finding term names quickly
 */
    private static HashMap/*<String,TermName>*/ terms = new HashMap();

    private final Name term;
    private Name type;

/** Constructor
 */
    private Name(String string, Name dual) {
        this.string = string;
        this.index = dual != null ? dual.index + 1 : 2 * terms.size();
        this.term = dual != null ? dual : this;
        this.type = dual != null ? this : null;
        if (dual == null) terms.put(string, this);
    }

/** create a term name from the bytes in cs[offset..offset+len-1].
 *  assume that bytes are in ascii format.
 */
    public static Name fromAscii(byte cs[], int offset, int len) {
        return fromString(SourceRepresentation.ascii2string(cs, offset, len));
    }

/** create a name from the bytes in cs[offset..offset+len-1];
 *  assume that characters are in source format
 */
    public static Name fromSource(byte cs[], int offset, int len) {
        byte[]  ascii = new byte[len * 2];
        int alen = SourceRepresentation.source2ascii(cs, offset, len, ascii);
        return fromAscii(ascii, 0, alen);
    }

/** create a name from the characters in string s
 */
    public static Name fromString(String s) {
        Object value = terms.get(s);
        if (value != null) return (Name)value;
        return new Name(s, null);
    }

/** return the string representation of this name
 */
    public String toString() {
        return string;
    }

/** is this name a term name?
 */
    public boolean isTermName() {
        return this == term;
    }

/** is this name a type name?
 */
    public boolean isTypeName() {
        return this == type;
    }

/** create a term name corresponding to this name
 */
    public Name toTermName() {
        return term;
    }

/** create a type name corresponding to this name
 */
    public Name toTypeName() {
        return type != null ? type : (type = new Name(string, this));
    }

/** return the string hash value of this name
 */
    public int hashCode() {
        return index;
    }

/** returns the length of this name
 */
    public int length() {
        return string.length();
    }

/** returns i'th char of this name
 */
    public char charAt(int i) {
        return string.charAt(i);
    }

/** returns first occurrence of char c in this name, -1 if not found
 */
    public int indexOf(char c) {
        return indexOf(c, 0);
    }

/** returns first occurrence of char c in this name from `start', -1 if not found
 */
    public int indexOf(char c, int start) {
        return string.indexOf(c, start);
    }

/** returns last occurrence of char c in this name, -1 if not found.
 */
    public int lastIndexOf(char c) {
        return string.lastIndexOf(c);
    }

/** returns the concatenation of this name and n
 */
    public Name append(Name n) {
        return fromString(string + n.string);
    }

/** is this name a variable identifier?
 */
    public boolean isVariable() {
        char first = string.charAt(0);
        return ((first >= 'a' && first <= 'z') || first == '_') &&
            this != Names.null_ &&
            this != Names.true_ &&
            this != Names.false_;
    }

    public static final Name ERROR = Name.fromString("<error>");
    static { ERROR.type = ERROR; }

/** precedence of this name
 */
    public int precedence() {
        if (this == ERROR)
            return -1;
        char ch = string.charAt(0);
        if (((ch >= 'A') && (ch <= 'Z')) ||
            ((ch >= 'a') && (ch <= 'z')))
            return 1;
        switch (ch) {
            case '|':
                return 2;
            case '^':
                return 3;
            case '&':
                return 4;
            case '<':
            case '>':
                return 5;
            case '=':
            case '!':
                return 6;
            case ':':
                return 7;
            case '+':
            case '-':
                return 8;
            case '*':
            case '/':
            case '%':
                return 9;
            default:
                return 10;
        }
    }

/** is this operator left associative
 */
    public boolean isLeftAssoc() {
        int length = string.length();
        return length > 0 && string.charAt(length - 1) != ':';
    }
}