OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 library fasta.scope; |
| 6 |
| 7 import 'builder.dart' show |
| 8 Builder, |
| 9 MixedAccessor; |
| 10 |
| 11 import '../errors.dart' show |
| 12 internalError; |
| 13 |
| 14 class Scope { |
| 15 final Map<String, Builder> local; |
| 16 |
| 17 final Scope parent; |
| 18 |
| 19 final bool isModifiable; |
| 20 |
| 21 Scope(this.local, this.parent, {this.isModifiable: true}); |
| 22 |
| 23 Scope createNestedScope({bool isModifiable: true}) { |
| 24 return new Scope(<String, Builder>{}, this, isModifiable: isModifiable); |
| 25 } |
| 26 |
| 27 Builder lookup(String name) { |
| 28 Builder builder = local[name]; |
| 29 if (builder != null) { |
| 30 if (builder.next != null) return lookupAmbiguous(name, builder, false); |
| 31 return builder.isSetter ? new AccessErrorBuilder(builder) : builder; |
| 32 } else { |
| 33 return parent?.lookup(name); |
| 34 } |
| 35 } |
| 36 |
| 37 Builder lookupSetter(String name) { |
| 38 Builder builder = local[name]; |
| 39 if (builder != null) { |
| 40 if (builder.next != null) return lookupAmbiguous(name, builder, true); |
| 41 if (builder.isField) { |
| 42 if (builder.isFinal) { |
| 43 return new AccessErrorBuilder(builder); |
| 44 } else { |
| 45 return builder; |
| 46 } |
| 47 } else if (builder.isSetter) { |
| 48 return builder; |
| 49 } else { |
| 50 return new AccessErrorBuilder(builder); |
| 51 } |
| 52 } else { |
| 53 return parent?.lookupSetter(name); |
| 54 } |
| 55 } |
| 56 |
| 57 Builder lookupAmbiguous(String name, Builder builder, bool setter) { |
| 58 assert(builder.next != null); |
| 59 if (builder is MixedAccessor) { |
| 60 return setter ? builder.setter : builder.getter; |
| 61 } |
| 62 Builder setterBuilder; |
| 63 Builder getterBuilder; |
| 64 Builder current = builder; |
| 65 while (current != null) { |
| 66 if (current.isGetter && getterBuilder == null) { |
| 67 getterBuilder = current; |
| 68 } else if (current.isSetter && setterBuilder == null) { |
| 69 setterBuilder = current; |
| 70 } else { |
| 71 return new AmbiguousBuilder(builder); |
| 72 } |
| 73 current = current.next; |
| 74 } |
| 75 assert(getterBuilder != null); |
| 76 assert(setterBuilder != null); |
| 77 return setter ? setterBuilder : getterBuilder; |
| 78 } |
| 79 |
| 80 // TODO(ahe): Rename to extend or something. |
| 81 void operator[]= (String name, Builder member) { |
| 82 if (isModifiable) { |
| 83 local[name] = member; |
| 84 } else { |
| 85 internalError("Can't extend an unmodifiable scope."); |
| 86 } |
| 87 } |
| 88 } |
| 89 |
| 90 class AccessErrorBuilder extends Builder { |
| 91 final Builder builder; |
| 92 |
| 93 AccessErrorBuilder(this.builder); |
| 94 |
| 95 Builder get parent => builder; |
| 96 |
| 97 get target => null; |
| 98 |
| 99 bool get isFinal => builder.isFinal; |
| 100 |
| 101 bool get isField => builder.isField; |
| 102 |
| 103 bool get isRegularMethod => builder.isRegularMethod; |
| 104 |
| 105 bool get isGetter => !builder.isGetter; |
| 106 |
| 107 bool get isSetter => !builder.isSetter; |
| 108 |
| 109 bool get isInstanceMember => builder.isInstanceMember; |
| 110 |
| 111 bool get isStatic => builder.isStatic; |
| 112 |
| 113 bool get isTopLevel => builder.isTopLevel; |
| 114 |
| 115 bool get isTypeDeclaration => builder.isTypeDeclaration; |
| 116 |
| 117 bool get isLocal => builder.isLocal; |
| 118 |
| 119 bool get hasProblem => true; |
| 120 } |
| 121 |
| 122 class AmbiguousBuilder extends Builder { |
| 123 final Builder builder; |
| 124 |
| 125 AmbiguousBuilder(this.builder); |
| 126 |
| 127 get target => null; |
| 128 |
| 129 bool get hasProblem => true; |
| 130 } |
OLD | NEW |