Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_backend/namer.dart

Issue 12049036: Cleanup the namer, and add a test with fields that used to clash with internal names used by the co… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of js_backend; 5 part of js_backend;
6 6
7 /** 7 /**
8 * Assigns JavaScript identifiers to Dart variables, class-names and members. 8 * Assigns JavaScript identifiers to Dart variables, class-names and members.
9 */ 9 */
10 class Namer implements ClosureNamer { 10 class Namer implements ClosureNamer {
11
12 static const javaScriptKeywords = const <String>[
13 // These are current keywords.
14 "break", "delete", "function", "return", "typeof", "case", "do", "if",
15 "switch", "var", "catch", "else", "in", "this", "void", "continue",
16 "false", "instanceof", "throw", "while", "debugger", "finally", "new",
17 "true", "with", "default", "for", "null", "try",
18
19 // These are future keywords.
20 "abstract", "double", "goto", "native", "static", "boolean", "enum",
21 "implements", "package", "super", "byte", "export", "import", "private",
22 "synchronized", "char", "extends", "int", "protected", "throws",
23 "class", "final", "interface", "public", "transient", "const", "float",
24 "long", "short", "volatile"
25 ];
26
27 static const reservedPropertySymbols =
28 const <String>["__proto__", "prototype", "constructor"];
29
11 static Set<String> _jsReserved = null; 30 static Set<String> _jsReserved = null;
12 Set<String> get jsReserved { 31 Set<String> get jsReserved {
13 if (_jsReserved == null) { 32 if (_jsReserved == null) {
14 _jsReserved = new Set<String>(); 33 _jsReserved = new Set<String>();
15 _jsReserved.addAll(JsNames.javaScriptKeywords); 34 _jsReserved.addAll(javaScriptKeywords);
16 _jsReserved.addAll(JsNames.reservedPropertySymbols); 35 _jsReserved.addAll(reservedPropertySymbols);
17 } 36 }
18 return _jsReserved; 37 return _jsReserved;
19 } 38 }
20 39
21 final String CURRENT_ISOLATE = r'$'; 40 final String CURRENT_ISOLATE = r'$';
22 41
23 /** 42 /**
24 * Map from top-level or static elements to their unique identifiers provided 43 * Map from top-level or static elements to their unique identifiers provided
25 * by [getName]. 44 * by [getName].
26 * 45 *
27 * Invariant: Keys must be declaration elements. 46 * Invariant: Keys must be declaration elements.
28 */ 47 */
29 final Compiler compiler; 48 final Compiler compiler;
30 final Map<Element, String> globals; 49 final Map<Element, String> globals;
31 final Map<String, LibraryElement> shortPrivateNameOwners; 50 final Map<String, LibraryElement> shortPrivateNameOwners;
32 final Set<String> usedGlobalNames; 51 final Set<String> usedGlobalNames;
33 final Set<String> usedInstanceNames; 52 final Set<String> usedInstanceNames;
34 final Map<String, String> globalNameMap; 53 final Map<String, String> globalNameMap;
35 final Map<String, String> instanceNameMap; 54 final Map<String, String> instanceNameMap;
55 final Map<String, String> operatorNameMap;
36 final Map<String, int> popularNameCounters; 56 final Map<String, int> popularNameCounters;
37 57
38 /** 58 /**
39 * A cache of names used for bailout methods. We make sure two 59 * A cache of names used for bailout methods. We make sure two
40 * bailout methods cannot have the same name because if the two 60 * bailout methods cannot have the same name because if the two
41 * bailout methods are in a class and a subclass, we would 61 * bailout methods are in a class and a subclass, we would
42 * call the wrong bailout method at runtime. To make it 62 * call the wrong bailout method at runtime. To make it
43 * simple, we don't keep track of inheritance and always avoid 63 * simple, we don't keep track of inheritance and always avoid
44 * similar names. 64 * similar names.
45 */ 65 */
46 final Set<String> usedBailoutInstanceNames; 66 final Set<String> usedBailoutInstanceNames;
47 final Map<Element, String> bailoutNames; 67 final Map<Element, String> bailoutNames;
48 68
49 final Map<Constant, String> constantNames; 69 final Map<Constant, String> constantNames;
50 70
51 Namer(this.compiler) 71 Namer(this.compiler)
52 : globals = new Map<Element, String>(), 72 : globals = new Map<Element, String>(),
53 shortPrivateNameOwners = new Map<String, LibraryElement>(), 73 shortPrivateNameOwners = new Map<String, LibraryElement>(),
54 bailoutNames = new Map<Element, String>(), 74 bailoutNames = new Map<Element, String>(),
55 usedBailoutInstanceNames = new Set<String>(), 75 usedBailoutInstanceNames = new Set<String>(),
56 usedGlobalNames = new Set<String>(), 76 usedGlobalNames = new Set<String>(),
57 usedInstanceNames = new Set<String>(), 77 usedInstanceNames = new Set<String>(),
58 instanceNameMap = new Map<String, String>(), 78 instanceNameMap = new Map<String, String>(),
79 operatorNameMap = new Map<String, String>(),
59 globalNameMap = new Map<String, String>(), 80 globalNameMap = new Map<String, String>(),
60 constantNames = new Map<Constant, String>(), 81 constantNames = new Map<Constant, String>(),
61 popularNameCounters = new Map<String, int>(); 82 popularNameCounters = new Map<String, int>();
62 83
63 String get isolateName => 'Isolate'; 84 String get isolateName => 'Isolate';
64 String get isolatePropertiesName => r'$isolateProperties'; 85 String get isolatePropertiesName => r'$isolateProperties';
65 /** 86 /**
66 * Some closures must contain their name. The name is stored in 87 * Some closures must contain their name. The name is stored in
67 * [STATIC_CLOSURE_NAME_NAME]. 88 * [STATIC_CLOSURE_NAME_NAME].
68 */ 89 */
(...skipping 17 matching lines...) Expand all
86 // The minifier always constructs a new name, using the argument as 107 // The minifier always constructs a new name, using the argument as
87 // input to its hashing algorithm. The given name does not need to be 108 // input to its hashing algorithm. The given name does not need to be
88 // valid. 109 // valid.
89 longName = stringConstant.value.slowToString(); 110 longName = stringConstant.value.slowToString();
90 } else { 111 } else {
91 longName = "C"; 112 longName = "C";
92 } 113 }
93 } else { 114 } else {
94 longName = "CONSTANT"; 115 longName = "CONSTANT";
95 } 116 }
96 result = getFreshName(longName, usedGlobalNames); 117 result = getFreshName(longName, usedGlobalNames, ensureSafe: true);
97 constantNames[constant] = result; 118 constantNames[constant] = result;
98 } 119 }
99 return result; 120 return result;
100 } 121 }
101 122
102 String breakLabelName(LabelElement label) { 123 String breakLabelName(LabelElement label) {
103 return '\$${label.labelName}\$${label.target.nestingLevel}'; 124 return '\$${label.labelName}\$${label.target.nestingLevel}';
104 } 125 }
105 126
106 String implicitBreakLabelName(TargetElement target) { 127 String implicitBreakLabelName(TargetElement target) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 163
143 // If a library name does not start with the [LIBRARY_PREFIX] then our 164 // If a library name does not start with the [LIBRARY_PREFIX] then our
144 // assumptions about clashing with mangled private members do not hold. 165 // assumptions about clashing with mangled private members do not hold.
145 String libraryName = getName(library); 166 String libraryName = getName(library);
146 assert(shouldMinify || libraryName.startsWith(LIBRARY_PREFIX)); 167 assert(shouldMinify || libraryName.startsWith(LIBRARY_PREFIX));
147 // TODO(erikcorry): Fix this with other manglings to avoid clashes. 168 // TODO(erikcorry): Fix this with other manglings to avoid clashes.
148 return '_lib$libraryName\$$nameString'; 169 return '_lib$libraryName\$$nameString';
149 } 170 }
150 171
151 String instanceMethodName(FunctionElement element) { 172 String instanceMethodName(FunctionElement element) {
152 SourceString name = Elements.operatorNameToIdentifier(element.name); 173 SourceString elementName = element.name;
174 SourceString name = operatorNameToIdentifier(elementName);
175 if (name != elementName) return getMappedOperatorName(name.slowToString());
176
153 LibraryElement library = element.getLibrary(); 177 LibraryElement library = element.getLibrary();
154 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { 178 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) {
155 ConstructorBodyElement bodyElement = element; 179 ConstructorBodyElement bodyElement = element;
156 name = bodyElement.constructor.name; 180 name = bodyElement.constructor.name;
157 } 181 }
158 FunctionSignature signature = element.computeSignature(compiler); 182 FunctionSignature signature = element.computeSignature(compiler);
159 String methodName = 183 String methodName =
160 '${privateName(library, name)}\$${signature.parameterCount}'; 184 '${privateName(library, name)}\$${signature.parameterCount}';
161 if (signature.optionalParametersAreNamed && 185 if (signature.optionalParametersAreNamed &&
162 !signature.optionalParameters.isEmpty) { 186 !signature.optionalParameters.isEmpty) {
163 StringBuffer buffer = new StringBuffer(); 187 StringBuffer buffer = new StringBuffer();
164 signature.orderedOptionalParameters.forEach((Element element) { 188 signature.orderedOptionalParameters.forEach((Element element) {
165 buffer.add('\$${JsNames.getValid(element.name.slowToString())}'); 189 buffer.add('\$${safeName(element.name.slowToString())}');
166 }); 190 });
167 methodName = '$methodName$buffer'; 191 methodName = '$methodName$buffer';
168 } 192 }
169 if (name == closureInvocationSelectorName) return methodName; 193 if (name == closureInvocationSelectorName) return methodName;
170 return getMappedInstanceName(methodName); 194 return getMappedInstanceName(methodName);
171 } 195 }
172 196
173 String publicInstanceMethodNameByArity(SourceString name, int arity) { 197 String publicInstanceMethodNameByArity(SourceString name, int arity) {
174 name = Elements.operatorNameToIdentifier(name); 198 SourceString newName = operatorNameToIdentifier(name);
199 if (newName != name) return getMappedOperatorName(newName.slowToString());
175 assert(!name.isPrivate()); 200 assert(!name.isPrivate());
176 var base = name.slowToString(); 201 var base = name.slowToString();
177 // We don't mangle the closure invoking function name because it 202 // We don't mangle the closure invoking function name because it
178 // is generated by string concatenation in applyFunction from 203 // is generated by string concatenation in applyFunction from
179 // js_helper.dart. 204 // js_helper.dart.
180 var proposedName = '$base\$$arity'; 205 var proposedName = '$base\$$arity';
181 if (name == closureInvocationSelectorName) return proposedName; 206 if (name == closureInvocationSelectorName) return proposedName;
182 return getMappedInstanceName(proposedName); 207 return getMappedInstanceName(proposedName);
183 } 208 }
184 209
185 String invocationName(Selector selector) { 210 String invocationName(Selector selector) {
186 if (selector.isGetter()) { 211 if (selector.isGetter()) {
187 String proposedName = privateName(selector.library, selector.name); 212 String proposedName = privateName(selector.library, selector.name);
188 return 'get\$${getMappedInstanceName(proposedName)}'; 213 return 'get\$${getMappedInstanceName(proposedName)}';
189 } else if (selector.isSetter()) { 214 } else if (selector.isSetter()) {
190 String proposedName = privateName(selector.library, selector.name); 215 String proposedName = privateName(selector.library, selector.name);
191 return 'set\$${getMappedInstanceName(proposedName)}'; 216 return 'set\$${getMappedInstanceName(proposedName)}';
192 } else { 217 } else {
193 SourceString name = Elements.operatorNameToIdentifier(selector.name); 218 SourceString name = selector.name;
219 if (selector.kind == SelectorKind.OPERATOR
220 || selector.kind == SelectorKind.INDEX) {
221 name = operatorNameToIdentifier(name);
222 assert(name != selector.name);
223 return getMappedOperatorName(name.slowToString());
224 }
225 assert(name == operatorNameToIdentifier(name));
194 StringBuffer buffer = new StringBuffer(); 226 StringBuffer buffer = new StringBuffer();
195 for (SourceString argumentName in selector.getOrderedNamedArguments()) { 227 for (SourceString argumentName in selector.getOrderedNamedArguments()) {
196 buffer.add(r'$'); 228 buffer.add(r'$');
197 argumentName.printOn(buffer); 229 argumentName.printOn(buffer);
198 } 230 }
199 String suffix = '\$${selector.argumentCount}$buffer'; 231 String suffix = '\$${selector.argumentCount}$buffer';
200 // We don't mangle the closure invoking function name because it 232 // We don't mangle the closure invoking function name because it
201 // is generated by string concatenation in applyFunction from 233 // is generated by string concatenation in applyFunction from
202 // js_helper.dart. 234 // js_helper.dart.
203 if (selector.isCall() && name == closureInvocationSelectorName) { 235 if (selector.isClosureCall()) {
204 return "${name.slowToString()}$suffix"; 236 return "${name.slowToString()}$suffix";
237 } else {
238 String proposedName = privateName(selector.library, name);
239 return getMappedInstanceName('$proposedName$suffix');
205 } 240 }
206 String proposedName = privateName(selector.library, name);
207 return getMappedInstanceName('$proposedName$suffix');
208 } 241 }
209 } 242 }
210 243
211 /** 244 /**
212 * Returns the internal name used for an invocation mirror of this selector. 245 * Returns the internal name used for an invocation mirror of this selector.
213 */ 246 */
214 String invocationMirrorInternalName(Selector selector) 247 String invocationMirrorInternalName(Selector selector)
215 => invocationName(selector); 248 => invocationName(selector);
216 249
217 String instanceFieldName(Element element) { 250 String instanceFieldName(Element element) {
218 String proposedName = privateName(element.getLibrary(), element.name); 251 String proposedName = privateName(element.getLibrary(), element.name);
219 return getMappedInstanceName(proposedName); 252 return getMappedInstanceName(proposedName);
220 } 253 }
221 254
222 // Construct a new name for the element based on the library and class it is 255 // Construct a new name for the element based on the library and class it is
223 // in. The name here is not important, we just need to make sure it is 256 // in. The name here is not important, we just need to make sure it is
224 // unique. If we are minifying, we actually construct the name from the 257 // unique. If we are minifying, we actually construct the name from the
225 // minified versions of the class and instance names, but the result is 258 // minified versions of the class and instance names, but the result is
226 // minified once again, so that is not visible in the end result. 259 // minified once again, so that is not visible in the end result.
227 String shadowedFieldName(Element fieldElement) { 260 String shadowedFieldName(Element fieldElement) {
228 // Check for following situation: Native field ${fieldElement.name} has 261 // Check for following situation: Native field ${fieldElement.name} has
229 // fixed JSName ${fieldElement.nativeName()}, but a subclass shadows this 262 // fixed JSName ${fieldElement.nativeName()}, but a subclass shadows this
230 // name. We normally handle that by renaming the superclass field, but we 263 // name. We normally handle that by renaming the superclass field, but we
231 // can't do that because native fields have fixed JsNames. In practice 264 // can't do that because native fields have fixed JavaScript names.
232 // this can't happen because we can't inherit from native classes. 265 // In practice this can't happen because we can't inherit from native
266 // classes.
233 assert (!fieldElement.hasFixedBackendName()); 267 assert (!fieldElement.hasFixedBackendName());
234 268
235 String libraryName = getName(fieldElement.getLibrary()); 269 String libraryName = getName(fieldElement.getLibrary());
236 String className = getName(fieldElement.getEnclosingClass()); 270 String className = getName(fieldElement.getEnclosingClass());
237 String instanceName = instanceFieldName(fieldElement); 271 String instanceName = instanceFieldName(fieldElement);
238 return getMappedInstanceName('$libraryName\$$className\$$instanceName'); 272 return getMappedInstanceName('$libraryName\$$className\$$instanceName');
239 } 273 }
240 274
241 String setterName(Element element) { 275 String setterName(Element element) {
242 // We dynamically create setters from the field-name. The setter name must 276 // We dynamically create setters from the field-name. The setter name must
(...skipping 26 matching lines...) Expand all
269 // We dynamically create getters from the field-name. The getter name must 303 // We dynamically create getters from the field-name. The getter name must
270 // therefore be derived from the instance field-name. 304 // therefore be derived from the instance field-name.
271 LibraryElement library = element.getLibrary(); 305 LibraryElement library = element.getLibrary();
272 String name = getMappedInstanceName(privateName(library, element.name)); 306 String name = getMappedInstanceName(privateName(library, element.name));
273 return 'get\$$name'; 307 return 'get\$$name';
274 } 308 }
275 309
276 String getMappedGlobalName(String proposedName) { 310 String getMappedGlobalName(String proposedName) {
277 var newName = globalNameMap[proposedName]; 311 var newName = globalNameMap[proposedName];
278 if (newName == null) { 312 if (newName == null) {
279 newName = getFreshName(proposedName, usedGlobalNames); 313 newName = getFreshName(proposedName, usedGlobalNames, ensureSafe: true);
280 globalNameMap[proposedName] = newName; 314 globalNameMap[proposedName] = newName;
281 } 315 }
282 return newName; 316 return newName;
283 } 317 }
284 318
285 String getMappedInstanceName(String proposedName) { 319 String getMappedInstanceName(String proposedName) {
286 var newName = instanceNameMap[proposedName]; 320 var newName = instanceNameMap[proposedName];
287 if (newName == null) { 321 if (newName == null) {
288 newName = getFreshName(proposedName, usedInstanceNames); 322 newName = getFreshName(proposedName, usedInstanceNames, ensureSafe: true);
289 instanceNameMap[proposedName] = newName; 323 instanceNameMap[proposedName] = newName;
290 } 324 }
291 return newName; 325 return newName;
292 } 326 }
293 327
294 String getFreshName(String proposedName, Set<String> usedNames) { 328 String getMappedOperatorName(String proposedName) {
329 var newName = operatorNameMap[proposedName];
330 if (newName == null) {
331 newName = getFreshName(
332 proposedName, usedInstanceNames, ensureSafe: false);
333 operatorNameMap[proposedName] = newName;
334 }
335 return newName;
336 }
337
338 String getFreshName(String proposedName,
339 Set<String> usedNames,
340 {bool ensureSafe: true}) {
295 var candidate; 341 var candidate;
296 proposedName = safeName(proposedName); 342 if (ensureSafe) {
343 proposedName = safeName(proposedName);
344 }
345 assert(!jsReserved.contains(proposedName));
297 if (!usedNames.contains(proposedName)) { 346 if (!usedNames.contains(proposedName)) {
298 candidate = proposedName; 347 candidate = proposedName;
299 } else { 348 } else {
300 var counter = popularNameCounters[proposedName]; 349 var counter = popularNameCounters[proposedName];
301 var i = counter == null ? 0 : counter; 350 var i = counter == null ? 0 : counter;
302 while (usedNames.contains("$proposedName$i")) { 351 while (usedNames.contains("$proposedName$i")) {
303 i++; 352 i++;
304 } 353 }
305 popularNameCounters[proposedName] = i + 1; 354 popularNameCounters[proposedName] = i + 1;
306 candidate = "$proposedName$i"; 355 candidate = "$proposedName$i";
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 kind == ElementKind.TYPEDEF || 474 kind == ElementKind.TYPEDEF ||
426 kind == ElementKind.LIBRARY || 475 kind == ElementKind.LIBRARY ||
427 kind == ElementKind.MALFORMED_TYPE) { 476 kind == ElementKind.MALFORMED_TYPE) {
428 bool fixedName = false; 477 bool fixedName = false;
429 if (kind == ElementKind.CLASS) { 478 if (kind == ElementKind.CLASS) {
430 ClassElement classElement = element; 479 ClassElement classElement = element;
431 } 480 }
432 if (Elements.isInstanceField(element)) { 481 if (Elements.isInstanceField(element)) {
433 fixedName = element.hasFixedBackendName(); 482 fixedName = element.hasFixedBackendName();
434 } 483 }
435 String result = 484 String result = fixedName
436 fixedName ? guess : getFreshName(guess, usedGlobalNames); 485 ? guess
486 : getFreshName(guess, usedGlobalNames, ensureSafe: true);
437 globals[element] = result; 487 globals[element] = result;
438 return result; 488 return result;
439 } 489 }
440 compiler.internalError('getName for unknown kind: ${element.kind}', 490 compiler.internalError('getName for unknown kind: ${element.kind}',
441 node: element.parseNode(compiler)); 491 node: element.parseNode(compiler));
442 } 492 }
443 } 493 }
444 494
445 String getLazyInitializerName(Element element) { 495 String getLazyInitializerName(Element element) {
446 assert(Elements.isStaticOrTopLevelField(element)); 496 assert(Elements.isStaticOrTopLevelField(element));
(...skipping 10 matching lines...) Expand all
457 507
458 String isolateBailoutAccess(Element element) { 508 String isolateBailoutAccess(Element element) {
459 String newName = getMappedGlobalName('${getName(element)}\$bailout'); 509 String newName = getMappedGlobalName('${getName(element)}\$bailout');
460 return '$CURRENT_ISOLATE.$newName'; 510 return '$CURRENT_ISOLATE.$newName';
461 } 511 }
462 512
463 String isolateLazyInitializerAccess(Element element) { 513 String isolateLazyInitializerAccess(Element element) {
464 return "$CURRENT_ISOLATE.${getLazyInitializerName(element)}"; 514 return "$CURRENT_ISOLATE.${getLazyInitializerName(element)}";
465 } 515 }
466 516
517 String operatorIsPrefix() => r'$is';
518
467 String operatorIs(Element element) { 519 String operatorIs(Element element) {
468 // TODO(erikcorry): Reduce from is$x to ix when we are minifying. 520 // TODO(erikcorry): Reduce from $isx to ix when we are minifying.
469 return 'is\$${getName(element)}'; 521 return '${operatorIsPrefix()}${getName(element)}';
470 } 522 }
471 523
524 /*
525 * Returns a name that does not clash with reserved JS keywords,
526 * and also ensures it won't clash with other identifiers.
527 */
472 String safeName(String name) { 528 String safeName(String name) {
473 if (jsReserved.contains(name) || name.startsWith('\$')) { 529 if (jsReserved.contains(name) || name.startsWith(r'$')) {
474 name = "\$$name"; 530 name = '\$$name';
475 assert(!jsReserved.contains(name));
476 } 531 }
532 assert(!jsReserved.contains(name));
477 return name; 533 return name;
478 } 534 }
535
536 SourceString operatorNameToIdentifier(SourceString name) {
537 if (name == null) return null;
538 String value = name.stringValue;
539 if (value == null) {
540 return name;
541 } else if (value == '==') {
542 return const SourceString(r'$eq');
543 } else if (value == '~') {
544 return const SourceString(r'$not');
545 } else if (value == '[]') {
546 return const SourceString(r'$index');
547 } else if (value == '[]=') {
548 return const SourceString(r'$indexSet');
549 } else if (value == '*') {
550 return const SourceString(r'$mul');
551 } else if (value == '/') {
552 return const SourceString(r'$div');
553 } else if (value == '%') {
554 return const SourceString(r'$mod');
555 } else if (value == '~/') {
556 return const SourceString(r'$tdiv');
557 } else if (value == '+') {
558 return const SourceString(r'$add');
559 } else if (value == '<<') {
560 return const SourceString(r'$shl');
561 } else if (value == '>>') {
562 return const SourceString(r'$shr');
563 } else if (value == '>=') {
564 return const SourceString(r'$ge');
565 } else if (value == '>') {
566 return const SourceString(r'$gt');
567 } else if (value == '<=') {
568 return const SourceString(r'$le');
569 } else if (value == '<') {
570 return const SourceString(r'$lt');
571 } else if (value == '&') {
572 return const SourceString(r'$and');
573 } else if (value == '^') {
574 return const SourceString(r'$xor');
575 } else if (value == '|') {
576 return const SourceString(r'$or');
577 } else if (value == '-') {
578 return const SourceString(r'$sub');
579 } else if (value == 'unary-') {
580 return const SourceString(r'$negate');
581 } else {
582 return name;
583 }
584 }
479 } 585 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698