| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 dart2js.semantics_visitor; | 5 part of dart2js.semantics_visitor; |
| 6 | 6 |
| 7 enum SendStructureKind { | 7 enum SendStructureKind { |
| 8 GET, | 8 GET, |
| 9 SET, | 9 SET, |
| 10 INVOKE, | 10 INVOKE, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 POSTFIX, | 21 POSTFIX, |
| 22 INDEX_PREFIX, | 22 INDEX_PREFIX, |
| 23 INDEX_POSTFIX, | 23 INDEX_POSTFIX, |
| 24 } | 24 } |
| 25 | 25 |
| 26 abstract class SendResolverMixin { | 26 abstract class SendResolverMixin { |
| 27 TreeElements get elements; | 27 TreeElements get elements; |
| 28 | 28 |
| 29 internalError(Spannable spannable, String message); | 29 internalError(Spannable spannable, String message); |
| 30 | 30 |
| 31 AccessSemantics handleStaticallyResolvedAccess(Send node, | 31 AccessSemantics handleCompoundErroneousSetterAccess( |
| 32 Element element, | 32 Send node, |
| 33 Element getter) { | 33 Element setter, |
| 34 Element getter) { |
| 35 assert(invariant(node, Elements.isUnresolved(setter), |
| 36 message: "Unexpected erreneous compound setter: $setter.")); |
| 37 if (getter.isStatic) { |
| 38 if (getter.isGetter) { |
| 39 return new CompoundAccessSemantics( |
| 40 CompoundAccessKind.UNRESOLVED_STATIC_SETTER, getter, setter); |
| 41 } else if (getter.isField) { |
| 42 // TODO(johnniwinther): Handle const field separately. |
| 43 assert(invariant(node, getter.isFinal || getter.isConst, |
| 44 message: "Field expected to be final or const.")); |
| 45 return new StaticAccess.finalStaticField(getter); |
| 46 } else if (getter.isFunction) { |
| 47 return new StaticAccess.staticMethod(getter); |
| 48 } else { |
| 49 return internalError(node, |
| 50 "Unexpected erroneous static compound: getter=$getter"); |
| 51 } |
| 52 } else if (getter.isTopLevel) { |
| 53 if (getter.isGetter) { |
| 54 return new CompoundAccessSemantics( |
| 55 CompoundAccessKind.UNRESOLVED_TOPLEVEL_SETTER, getter, setter); |
| 56 } else if (getter.isField) { |
| 57 // TODO(johnniwinther): Handle const field separately. |
| 58 assert(invariant(node, getter.isFinal || getter.isConst, |
| 59 message: "Field expected to be final or const.")); |
| 60 return new StaticAccess.finalTopLevelField(getter); |
| 61 } else if (getter.isFunction) { |
| 62 return new StaticAccess.topLevelMethod(getter); |
| 63 } else { |
| 64 return internalError(node, |
| 65 "Unexpected erroneous top level compound: getter=$getter"); |
| 66 } |
| 67 } else if (getter.isParameter) { |
| 68 assert(invariant(node, getter.isFinal, |
| 69 message: "Parameter expected to be final.")); |
| 70 return new StaticAccess.finalParameter(getter); |
| 71 } else if (getter.isLocal) { |
| 72 if (getter.isVariable) { |
| 73 // TODO(johnniwinther): Handle const variable separately. |
| 74 assert(invariant(node, getter.isFinal || getter.isConst, |
| 75 message: "Variable expected to be final or const.")); |
| 76 return new StaticAccess.finalLocalVariable(getter); |
| 77 } else if (getter.isFunction) { |
| 78 return new StaticAccess.localFunction(getter); |
| 79 } else { |
| 80 return internalError(node, |
| 81 "Unexpected erroneous local compound: getter=$getter"); |
| 82 } |
| 83 } else if (getter.isErroneous) { |
| 84 return new StaticAccess.unresolved(getter); |
| 85 } else { |
| 86 return internalError(node, |
| 87 "Unexpected erroneous compound: getter=$getter"); |
| 88 } |
| 89 } |
| 90 |
| 91 AccessSemantics handleStaticallyResolvedAccess( |
| 92 Send node, |
| 93 Element element, |
| 94 Element getter, |
| 95 {bool isCompound}) { |
| 96 if (element == null) { |
| 97 assert(invariant(node, isCompound, message: |
| 98 "Non-compound static access without element.")); |
| 99 assert(invariant(node, getter != null, message: |
| 100 "Compound static access without element.")); |
| 101 return handleCompoundErroneousSetterAccess(node, element, getter); |
| 102 } |
| 34 if (element.isErroneous) { | 103 if (element.isErroneous) { |
| 104 if (isCompound) { |
| 105 return handleCompoundErroneousSetterAccess(node, element, getter); |
| 106 } |
| 35 return new StaticAccess.unresolved(element); | 107 return new StaticAccess.unresolved(element); |
| 36 } else if (element.isParameter) { | 108 } else if (element.isParameter) { |
| 37 return new StaticAccess.parameter(element); | 109 return new StaticAccess.parameter(element); |
| 38 } else if (element.isLocal) { | 110 } else if (element.isLocal) { |
| 39 if (element.isFunction) { | 111 if (element.isFunction) { |
| 40 return new StaticAccess.localFunction(element); | 112 return new StaticAccess.localFunction(element); |
| 41 } else { | 113 } else { |
| 42 return new StaticAccess.localVariable(element); | 114 return new StaticAccess.localVariable(element); |
| 43 } | 115 } |
| 44 } else if (element.isStatic) { | 116 } else if (element.isStatic) { |
| 45 if (element.isField) { | 117 if (element.isField) { |
| 118 if (element.isFinal || element.isConst) { |
| 119 // TODO(johnniwinther): Handle const field separately. |
| 120 return new StaticAccess.finalStaticField(element); |
| 121 } |
| 46 return new StaticAccess.staticField(element); | 122 return new StaticAccess.staticField(element); |
| 47 } else if (element.isGetter) { | 123 } else if (element.isGetter) { |
| 124 if (isCompound) { |
| 125 return new CompoundAccessSemantics( |
| 126 CompoundAccessKind.UNRESOLVED_STATIC_SETTER, element, null); |
| 127 } |
| 48 return new StaticAccess.staticGetter(element); | 128 return new StaticAccess.staticGetter(element); |
| 49 } else if (element.isSetter) { | 129 } else if (element.isSetter) { |
| 50 if (getter != null) { | 130 if (getter != null) { |
| 51 CompoundAccessKind accessKind; | 131 CompoundAccessKind accessKind; |
| 52 if (getter.isGetter) { | 132 if (getter.isErroneous) { |
| 133 accessKind = CompoundAccessKind.UNRESOLVED_STATIC_GETTER; |
| 134 } else if (getter.isAbstractField) { |
| 135 AbstractFieldElement abstractField = getter; |
| 136 if (abstractField.getter == null) { |
| 137 accessKind = CompoundAccessKind.UNRESOLVED_STATIC_GETTER; |
| 138 } else { |
| 139 // TODO(johnniwinther): This might be dead code. |
| 140 getter = abstractField.getter; |
| 141 accessKind = CompoundAccessKind.STATIC_GETTER_SETTER; |
| 142 } |
| 143 } else if (getter.isGetter) { |
| 53 accessKind = CompoundAccessKind.STATIC_GETTER_SETTER; | 144 accessKind = CompoundAccessKind.STATIC_GETTER_SETTER; |
| 54 } else { | 145 } else { |
| 55 accessKind = CompoundAccessKind.STATIC_METHOD_SETTER; | 146 accessKind = CompoundAccessKind.STATIC_METHOD_SETTER; |
| 56 } | 147 } |
| 57 return new CompoundAccessSemantics( | 148 return new CompoundAccessSemantics( |
| 58 accessKind, getter, element); | 149 accessKind, getter, element); |
| 59 } else { | 150 } else { |
| 60 return new StaticAccess.staticSetter(element); | 151 return new StaticAccess.staticSetter(element); |
| 61 } | 152 } |
| 62 } else { | 153 } else { |
| 63 return new StaticAccess.staticMethod(element); | 154 return new StaticAccess.staticMethod(element); |
| 64 } | 155 } |
| 65 } else if (element.isTopLevel) { | 156 } else if (element.isTopLevel) { |
| 66 if (element.isField) { | 157 if (element.isField) { |
| 158 if (element.isFinal || element.isConst) { |
| 159 // TODO(johnniwinther): Handle const field separately. |
| 160 return new StaticAccess.finalTopLevelField(element); |
| 161 } |
| 67 return new StaticAccess.topLevelField(element); | 162 return new StaticAccess.topLevelField(element); |
| 68 } else if (element.isGetter) { | 163 } else if (element.isGetter) { |
| 69 return new StaticAccess.topLevelGetter(element); | 164 return new StaticAccess.topLevelGetter(element); |
| 70 } else if (element.isSetter) { | 165 } else if (element.isSetter) { |
| 71 if (getter != null) { | 166 if (getter != null) { |
| 72 CompoundAccessKind accessKind; | 167 CompoundAccessKind accessKind; |
| 73 if (getter.isGetter) { | 168 if (getter.isErroneous) { |
| 169 accessKind = CompoundAccessKind.UNRESOLVED_TOPLEVEL_GETTER; |
| 170 } else if (getter.isAbstractField) { |
| 171 AbstractFieldElement abstractField = getter; |
| 172 if (abstractField.getter == null) { |
| 173 accessKind = CompoundAccessKind.UNRESOLVED_TOPLEVEL_GETTER; |
| 174 } else { |
| 175 // TODO(johnniwinther): This might be dead code. |
| 176 getter = abstractField.getter; |
| 177 accessKind = CompoundAccessKind.TOPLEVEL_GETTER_SETTER; |
| 178 } |
| 179 } else if (getter.isGetter) { |
| 74 accessKind = CompoundAccessKind.TOPLEVEL_GETTER_SETTER; | 180 accessKind = CompoundAccessKind.TOPLEVEL_GETTER_SETTER; |
| 75 } else { | 181 } else { |
| 76 accessKind = CompoundAccessKind.TOPLEVEL_METHOD_SETTER; | 182 accessKind = CompoundAccessKind.TOPLEVEL_METHOD_SETTER; |
| 77 } | 183 } |
| 78 return new CompoundAccessSemantics( | 184 return new CompoundAccessSemantics( |
| 79 accessKind, getter, element); | 185 accessKind, getter, element); |
| 80 } else { | 186 } else { |
| 81 return new StaticAccess.topLevelSetter(element); | 187 return new StaticAccess.topLevelSetter(element); |
| 82 } | 188 } |
| 83 } else { | 189 } else { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 kind = SendStructureKind.BINARY; | 314 kind = SendStructureKind.BINARY; |
| 209 break; | 315 break; |
| 210 } | 316 } |
| 211 } else { | 317 } else { |
| 212 return const InvalidBinaryStructure(); | 318 return const InvalidBinaryStructure(); |
| 213 } | 319 } |
| 214 } | 320 } |
| 215 } | 321 } |
| 216 AccessSemantics semantics = computeAccessSemantics( | 322 AccessSemantics semantics = computeAccessSemantics( |
| 217 node, | 323 node, |
| 218 isGetOrSet: kind == SendStructureKind.GET || | 324 isSet: kind == SendStructureKind.SET, |
| 219 kind == SendStructureKind.SET, | |
| 220 isInvoke: kind == SendStructureKind.INVOKE, | 325 isInvoke: kind == SendStructureKind.INVOKE, |
| 221 isCompound: kind == SendStructureKind.COMPOUND || | 326 isCompound: kind == SendStructureKind.COMPOUND || |
| 222 kind == SendStructureKind.COMPOUND_INDEX_SET || | 327 kind == SendStructureKind.COMPOUND_INDEX_SET || |
| 223 kind == SendStructureKind.PREFIX || | 328 kind == SendStructureKind.PREFIX || |
| 224 kind == SendStructureKind.POSTFIX || | 329 kind == SendStructureKind.POSTFIX || |
| 225 kind == SendStructureKind.INDEX_PREFIX || | 330 kind == SendStructureKind.INDEX_PREFIX || |
| 226 kind == SendStructureKind.INDEX_POSTFIX); | 331 kind == SendStructureKind.INDEX_POSTFIX); |
| 227 if (semantics == null) { | 332 if (semantics == null) { |
| 228 return internalError(node, 'No semantics for $node'); | 333 return internalError(node, 'No semantics for $node'); |
| 229 } | 334 } |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 elements.getGetterSelectorInComplexSendSet(node); | 412 elements.getGetterSelectorInComplexSendSet(node); |
| 308 return new PostfixStructure( | 413 return new PostfixStructure( |
| 309 semantics, | 414 semantics, |
| 310 incDecOperator, | 415 incDecOperator, |
| 311 getterSelector, | 416 getterSelector, |
| 312 selector); | 417 selector); |
| 313 } | 418 } |
| 314 } | 419 } |
| 315 | 420 |
| 316 AccessSemantics computeAccessSemantics(Send node, | 421 AccessSemantics computeAccessSemantics(Send node, |
| 317 {bool isGetOrSet: false, | 422 {bool isSet: false, |
| 318 bool isInvoke: false, | 423 bool isInvoke: false, |
| 319 bool isCompound: false}) { | 424 bool isCompound: false}) { |
| 320 Element element = elements[node]; | 425 Element element = elements[node]; |
| 321 Element getter = isCompound ? elements[node.selector] : null; | 426 Element getter = isCompound ? elements[node.selector] : null; |
| 322 if (elements.isTypeLiteral(node)) { | 427 if (elements.isTypeLiteral(node)) { |
| 323 DartType dartType = elements.getTypeLiteralType(node); | 428 DartType dartType = elements.getTypeLiteralType(node); |
| 324 // TODO(johnniwinther): Handle deferred constants. There are runtime | 429 // TODO(johnniwinther): Handle deferred constants. There are runtime |
| 325 // but not compile-time constants and should have their own | 430 // but not compile-time constants and should have their own |
| 326 // [DeferredConstantExpression] class. | 431 // [DeferredConstantExpression] class. |
| 327 ConstantExpression constant = elements.getConstant( | 432 ConstantExpression constant = elements.getConstant( |
| 328 isInvoke ? node.selector : node); | 433 isInvoke || isSet || isCompound ? node.selector : node); |
| 329 switch (dartType.kind) { | 434 switch (dartType.kind) { |
| 330 case TypeKind.INTERFACE: | 435 case TypeKind.INTERFACE: |
| 331 return new ConstantAccess.classTypeLiteral(constant); | 436 return new ConstantAccess.classTypeLiteral(constant); |
| 332 case TypeKind.TYPEDEF: | 437 case TypeKind.TYPEDEF: |
| 333 return new ConstantAccess.typedefTypeLiteral(constant); | 438 return new ConstantAccess.typedefTypeLiteral(constant); |
| 334 case TypeKind.TYPE_VARIABLE: | 439 case TypeKind.TYPE_VARIABLE: |
| 335 return new StaticAccess.typeParameterTypeLiteral(dartType.element); | 440 return new StaticAccess.typeParameterTypeLiteral(dartType.element); |
| 336 case TypeKind.DYNAMIC: | 441 case TypeKind.DYNAMIC: |
| 337 return new ConstantAccess.dynamicTypeLiteral(constant); | 442 return new ConstantAccess.dynamicTypeLiteral(constant); |
| 338 default: | 443 default: |
| 339 return internalError(node, "Unexpected type literal type: $dartType"); | 444 return internalError(node, "Unexpected type literal type: $dartType"); |
| 340 } | 445 } |
| 341 } else if (node.isSuperCall) { | 446 } else if (node.isSuperCall) { |
| 342 if (Elements.isUnresolved(element)) { | 447 if (Elements.isUnresolved(element)) { |
| 343 if (isCompound) { | 448 if (isCompound) { |
| 344 if (Elements.isUnresolved(getter)) { | 449 if (Elements.isUnresolved(getter)) { |
| 345 // TODO(johnniwinther): Ensure that [getter] is not null. This | 450 // TODO(johnniwinther): Ensure that [getter] is not null. This |
| 346 // happens in the case of missing super getter. | 451 // happens in the case of missing super getter. |
| 347 return new CompoundAccessSemantics( | 452 return new StaticAccess.unresolvedSuper(element); |
| 348 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element); | 453 } else if (getter.isField) { |
| 454 assert(invariant(node, getter.isFinal, |
| 455 message: "Super field expected to be final.")); |
| 456 return new StaticAccess.superFinalField(getter); |
| 457 } else if (getter.isFunction) { |
| 458 if (node.isIndex) { |
| 459 return new CompoundAccessSemantics( |
| 460 CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, element); |
| 461 } else { |
| 462 return new StaticAccess.superMethod(getter); |
| 463 } |
| 349 } else { | 464 } else { |
| 350 return new CompoundAccessSemantics( | 465 return new CompoundAccessSemantics( |
| 351 CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, element); | 466 CompoundAccessKind.UNRESOLVED_SUPER_SETTER, getter, element); |
| 352 } | 467 } |
| 353 } else { | 468 } else { |
| 354 return new StaticAccess.unresolvedSuper(element); | 469 return new StaticAccess.unresolvedSuper(element); |
| 355 } | 470 } |
| 356 } else if (isCompound && Elements.isUnresolved(getter)) { | 471 } else if (isCompound && Elements.isUnresolved(getter)) { |
| 357 // TODO(johnniwinther): Ensure that [getter] is not null. This happens | 472 // TODO(johnniwinther): Ensure that [getter] is not null. This happens |
| 358 // in the case of missing super getter. | 473 // in the case of missing super getter. |
| 359 return new CompoundAccessSemantics( | 474 return new CompoundAccessSemantics( |
| 360 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element); | 475 CompoundAccessKind.UNRESOLVED_SUPER_GETTER, getter, element); |
| 361 } else if (element.isField) { | 476 } else if (element.isField) { |
| 362 if (getter != null && getter != element) { | 477 if (getter != null && getter != element) { |
| 363 CompoundAccessKind accessKind; | 478 CompoundAccessKind accessKind; |
| 364 if (getter.isField) { | 479 if (getter.isField) { |
| 365 accessKind = CompoundAccessKind.SUPER_FIELD_FIELD; | 480 accessKind = CompoundAccessKind.SUPER_FIELD_FIELD; |
| 366 } else if (getter.isGetter) { | 481 } else if (getter.isGetter) { |
| 367 accessKind = CompoundAccessKind.SUPER_GETTER_FIELD; | 482 accessKind = CompoundAccessKind.SUPER_GETTER_FIELD; |
| 368 } else { | 483 } else { |
| 369 return internalError(node, | 484 return internalError(node, |
| 370 "Unsupported super call: $node : $element/$getter."); | 485 "Unsupported super call: $node : $element/$getter."); |
| 371 } | 486 } |
| 372 return new CompoundAccessSemantics(accessKind, getter, element); | 487 return new CompoundAccessSemantics(accessKind, getter, element); |
| 488 } else if (element.isFinal) { |
| 489 return new StaticAccess.superFinalField(element); |
| 373 } | 490 } |
| 374 return new StaticAccess.superField(element); | 491 return new StaticAccess.superField(element); |
| 375 } else if (element.isGetter) { | 492 } else if (element.isGetter) { |
| 376 return new StaticAccess.superGetter(element); | 493 return new StaticAccess.superGetter(element); |
| 377 } else if (element.isSetter) { | 494 } else if (element.isSetter) { |
| 378 if (getter != null) { | 495 if (getter != null) { |
| 379 CompoundAccessKind accessKind; | 496 CompoundAccessKind accessKind; |
| 380 if (getter.isField) { | 497 if (getter.isField) { |
| 381 accessKind = CompoundAccessKind.SUPER_FIELD_SETTER; | 498 accessKind = CompoundAccessKind.SUPER_FIELD_SETTER; |
| 382 } else if (getter.isGetter) { | 499 } else if (getter.isGetter) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 398 } else if (Elements.isClosureSend(node, element)) { | 515 } else if (Elements.isClosureSend(node, element)) { |
| 399 if (element == null) { | 516 if (element == null) { |
| 400 if (node.selector.isThis()) { | 517 if (node.selector.isThis()) { |
| 401 return new AccessSemantics.thisAccess(); | 518 return new AccessSemantics.thisAccess(); |
| 402 } else { | 519 } else { |
| 403 return new AccessSemantics.expression(); | 520 return new AccessSemantics.expression(); |
| 404 } | 521 } |
| 405 } else if (Elements.isErroneous(element)) { | 522 } else if (Elements.isErroneous(element)) { |
| 406 return new StaticAccess.unresolved(element); | 523 return new StaticAccess.unresolved(element); |
| 407 } else { | 524 } else { |
| 408 return handleStaticallyResolvedAccess(node, element, getter); | 525 return handleStaticallyResolvedAccess( |
| 526 node, element, getter, isCompound: isCompound); |
| 409 } | 527 } |
| 410 } else { | 528 } else { |
| 411 if (Elements.isErroneous(element)) { | 529 bool isDynamicAccess(Element e) => e == null || e.isInstanceMember; |
| 412 return new StaticAccess.unresolved(element); | 530 |
| 413 } else if (isCompound && Elements.isErroneous(getter)) { | 531 if (isDynamicAccess(element) && |
| 414 return new StaticAccess.unresolved(getter); | 532 (!isCompound || isDynamicAccess(getter))) { |
| 415 } else if (element == null || element.isInstanceMember) { | |
| 416 if (node.receiver == null || node.receiver.isThis()) { | 533 if (node.receiver == null || node.receiver.isThis()) { |
| 417 return new AccessSemantics.thisProperty(); | 534 return new AccessSemantics.thisProperty(); |
| 418 } else { | 535 } else { |
| 419 return new DynamicAccess.dynamicProperty(node.receiver); | 536 return new DynamicAccess.dynamicProperty(node.receiver); |
| 420 } | 537 } |
| 421 } else if (element.impliesType) { | 538 } else if (element != null && element.impliesType) { |
| 422 // TODO(johnniwinther): Provide an [ErroneousElement]. | 539 // TODO(johnniwinther): Provide an [ErroneousElement]. |
| 423 // This happens for code like `C.this`. | 540 // This happens for code like `C.this`. |
| 424 return new StaticAccess.unresolved(null); | 541 return new StaticAccess.unresolved(null); |
| 425 } else { | 542 } else { |
| 426 return handleStaticallyResolvedAccess(node, element, getter); | 543 return handleStaticallyResolvedAccess( |
| 544 node, element, getter, isCompound: isCompound); |
| 427 } | 545 } |
| 428 } | 546 } |
| 429 } | 547 } |
| 430 | 548 |
| 431 ConstructorAccessSemantics computeConstructorAccessSemantics( | 549 ConstructorAccessSemantics computeConstructorAccessSemantics( |
| 432 ConstructorElement constructor, | 550 ConstructorElement constructor, |
| 433 DartType type, | 551 DartType type, |
| 434 {bool mustBeConstant: false}) { | 552 {bool mustBeConstant: false}) { |
| 435 if (mustBeConstant && !constructor.isConst) { | 553 if (mustBeConstant && !constructor.isConst) { |
| 436 return new ConstructorAccessSemantics( | 554 return new ConstructorAccessSemantics( |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 813 return internalError(node, "Unexpected variable $element."); | 931 return internalError(node, "Unexpected variable $element."); |
| 814 } | 932 } |
| 815 if (element.isConst) { | 933 if (element.isConst) { |
| 816 ConstantExpression constant = elements.getConstant(element.initializer); | 934 ConstantExpression constant = elements.getConstant(element.initializer); |
| 817 return new ConstantVariableStructure(kind, node, element, constant); | 935 return new ConstantVariableStructure(kind, node, element, constant); |
| 818 } else { | 936 } else { |
| 819 return new NonConstantVariableStructure(kind, node, element); | 937 return new NonConstantVariableStructure(kind, node, element); |
| 820 } | 938 } |
| 821 } | 939 } |
| 822 } | 940 } |
| OLD | NEW |