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.builder_accessors; |
| 6 |
| 7 export 'frontend_accessors.dart' show |
| 8 wrapInvalid; |
| 9 |
| 10 import 'frontend_accessors.dart' show |
| 11 Accessor; |
| 12 |
| 13 import 'package:kernel/ast.dart'; |
| 14 |
| 15 import 'package:kernel/core_types.dart' show |
| 16 CoreTypes; |
| 17 |
| 18 import '../errors.dart' show |
| 19 internalError; |
| 20 |
| 21 import 'frontend_accessors.dart' as kernel show |
| 22 IndexAccessor, |
| 23 NullAwarePropertyAccessor, |
| 24 PropertyAccessor, |
| 25 StaticAccessor, |
| 26 SuperPropertyAccessor, |
| 27 ThisIndexAccessor, |
| 28 ThisPropertyAccessor, |
| 29 VariableAccessor; |
| 30 |
| 31 import 'frontend_accessors.dart' show |
| 32 buildIsNull, |
| 33 makeLet; |
| 34 |
| 35 import 'kernel_builder.dart' show |
| 36 Builder, |
| 37 KernelClassBuilder, |
| 38 PrefixBuilder, |
| 39 TypeDeclarationBuilder; |
| 40 |
| 41 abstract class BuilderHelper { |
| 42 Uri get uri; |
| 43 |
| 44 CoreTypes get coreTypes; |
| 45 |
| 46 Constructor lookupConstructor(Name name, {bool isSuper}); |
| 47 |
| 48 Expression toSuperMethodInvocation(MethodInvocation node); |
| 49 |
| 50 Expression toValue(node); |
| 51 |
| 52 Member lookupSuperMember(Name name, {bool isSetter: false}); |
| 53 |
| 54 builderToFirstExpression(Builder builder, String name, int charOffset); |
| 55 |
| 56 finishSend(Object receiver, Arguments arguments, int charOffset); |
| 57 |
| 58 Expression buildCompileTimeError(error, [int charOffset]); |
| 59 |
| 60 Initializer buildCompileTimeErrorIntializer(error, [int charOffset]); |
| 61 |
| 62 Expression buildStaticInvocation(Procedure target, Arguments arguments); |
| 63 |
| 64 Expression buildProblemExpression(Builder builder, String name); |
| 65 } |
| 66 |
| 67 abstract class BuilderAccessor implements Accessor { |
| 68 BuilderHelper get helper; |
| 69 |
| 70 int get charOffset; |
| 71 |
| 72 String get plainNameForRead; |
| 73 |
| 74 Uri get uri => helper.uri; |
| 75 |
| 76 CoreTypes get coreTypes => helper.coreTypes; |
| 77 |
| 78 String get plainNameForWrite => plainNameForRead; |
| 79 |
| 80 Expression buildForEffect() => buildSimpleRead(); |
| 81 |
| 82 Initializer buildFieldInitializer( |
| 83 Map<String, FieldInitializer> initializers) { |
| 84 // TODO(ahe): This error message is really bad. |
| 85 return helper.buildCompileTimeErrorIntializer( |
| 86 "Can't use $plainNameForRead here.", charOffset); |
| 87 } |
| 88 |
| 89 Expression makeInvalidRead() { |
| 90 return throwNoSuchMethodError(plainNameForRead, new Arguments.empty(), uri, |
| 91 charOffset, coreTypes, isGetter: true); |
| 92 } |
| 93 |
| 94 Expression makeInvalidWrite(Expression value) { |
| 95 return throwNoSuchMethodError(plainNameForWrite, |
| 96 new Arguments(<Expression>[value]), uri, charOffset, coreTypes, |
| 97 isSetter: true); |
| 98 } |
| 99 |
| 100 Expression doInvocation(int charOffset, Arguments arguments); |
| 101 |
| 102 buildPropertyAccess(IncompleteSend send, bool isNullAware) { |
| 103 if (send is SendAccessor) { |
| 104 return buildMethodInvocation(buildSimpleRead(), send.name, send.arguments, |
| 105 charOffset, isNullAware: isNullAware); |
| 106 } else { |
| 107 return PropertyAccessor.make(helper, charOffset, buildSimpleRead(), |
| 108 send.name, null, null, isNullAware); |
| 109 } |
| 110 } |
| 111 |
| 112 Expression buildThrowNoSuchMethodError(Arguments arguments) { |
| 113 bool isGetter = false; |
| 114 if (arguments == null) { |
| 115 arguments = new Arguments.empty(); |
| 116 isGetter = true; |
| 117 } |
| 118 return throwNoSuchMethodError(plainNameForWrite, arguments, uri, charOffset, |
| 119 coreTypes, isGetter: isGetter); |
| 120 } |
| 121 |
| 122 bool get isThisPropertyAccessor => false; |
| 123 } |
| 124 |
| 125 abstract class CompileTimeErrorAccessor implements Accessor { |
| 126 Expression buildError(); |
| 127 |
| 128 Name get name => internalError("Unsupported operation."); |
| 129 |
| 130 String get plainNameForRead => name.name; |
| 131 |
| 132 withReceiver(Object receiver, {bool isNullAware}) => this; |
| 133 |
| 134 Initializer buildFieldInitializer( |
| 135 Map<String, FieldInitializer> initializers) { |
| 136 return new LocalInitializer(new VariableDeclaration.forValue(buildError())); |
| 137 } |
| 138 |
| 139 doInvocation(int charOffset, Arguments arguments) => this; |
| 140 |
| 141 buildPropertyAccess(IncompleteSend send, bool isNullAware) => this; |
| 142 |
| 143 buildThrowNoSuchMethodError(Arguments arguments) => this; |
| 144 |
| 145 Expression buildAssignment(Expression value, {bool voidContext: false}) { |
| 146 return buildError(); |
| 147 } |
| 148 |
| 149 Expression buildCompoundAssignment(Name binaryOperator, Expression value, |
| 150 {bool voidContext: false, Procedure interfaceTarget}) { |
| 151 return buildError(); |
| 152 } |
| 153 |
| 154 Expression buildPrefixIncrement(Name binaryOperator, |
| 155 {bool voidContext: false, Procedure interfaceTarget}) { |
| 156 return buildError(); |
| 157 } |
| 158 |
| 159 Expression buildPostfixIncrement(Name binaryOperator, |
| 160 {bool voidContext: false, Procedure interfaceTarget}) { |
| 161 return buildError(); |
| 162 } |
| 163 |
| 164 Expression buildNullAwareAssignment(Expression value, DartType type, |
| 165 {bool voidContext: false}) { |
| 166 return buildError(); |
| 167 } |
| 168 |
| 169 Expression buildSimpleRead() => buildError(); |
| 170 |
| 171 Expression makeInvalidRead() => buildError(); |
| 172 |
| 173 Expression makeInvalidWrite(Expression value) => buildError(); |
| 174 } |
| 175 |
| 176 class ThisAccessor extends BuilderAccessor { |
| 177 final BuilderHelper helper; |
| 178 |
| 179 final int charOffset; |
| 180 |
| 181 final bool isInitializer; |
| 182 |
| 183 final bool isSuper; |
| 184 |
| 185 ThisAccessor(this.helper, this.charOffset, this.isInitializer, |
| 186 {this.isSuper: false}); |
| 187 |
| 188 String get plainNameForRead => internalError(isSuper ? "super" : "this"); |
| 189 |
| 190 Expression buildSimpleRead() { |
| 191 if (!isSuper) { |
| 192 return new ThisExpression(); |
| 193 } else { |
| 194 return helper.buildCompileTimeError( |
| 195 "Can't use `super` as an expression.", charOffset); |
| 196 } |
| 197 } |
| 198 |
| 199 Initializer buildFieldInitializer( |
| 200 Map<String, FieldInitializer> initializers) { |
| 201 String keyword = isSuper ? "super" : "this"; |
| 202 return helper.buildCompileTimeErrorIntializer( |
| 203 "Can't use '$keyword' here, did you mean '$keyword()'?", charOffset); |
| 204 } |
| 205 |
| 206 buildPropertyAccess(IncompleteSend send, bool isNullAware) { |
| 207 if (isInitializer && send is SendAccessor) { |
| 208 return buildConstructorInitializer( |
| 209 send.charOffset, send.name, send.arguments); |
| 210 } |
| 211 if (send is SendAccessor) { |
| 212 // Notice that 'this' or 'super' can't be null. So we can ignore the |
| 213 // value of [isNullAware]. |
| 214 MethodInvocation result = buildMethodInvocation(new ThisExpression(), |
| 215 send.name, send.arguments, charOffset); |
| 216 return isSuper ? helper.toSuperMethodInvocation(result) : result; |
| 217 } else { |
| 218 if (isSuper) { |
| 219 Member getter = helper.lookupSuperMember(send.name); |
| 220 Member setter = helper.lookupSuperMember(send.name, isSetter: true); |
| 221 return new SuperPropertyAccessor(helper, charOffset, send.name, getter, |
| 222 setter); |
| 223 } else { |
| 224 return new ThisPropertyAccessor(helper, charOffset, send.name, null, |
| 225 null); |
| 226 } |
| 227 } |
| 228 } |
| 229 |
| 230 doInvocation(int charOffset, Arguments arguments) { |
| 231 if (isInitializer) { |
| 232 return buildConstructorInitializer(charOffset, new Name(""), arguments); |
| 233 } else { |
| 234 return buildMethodInvocation(new ThisExpression(), new Name("call"), |
| 235 arguments, charOffset); |
| 236 } |
| 237 } |
| 238 |
| 239 Initializer buildConstructorInitializer(int charOffset, Name name, |
| 240 Arguments arguments) { |
| 241 Constructor constructor = helper.lookupConstructor(name, isSuper: isSuper); |
| 242 Initializer result; |
| 243 if (constructor == null) { |
| 244 result = new LocalInitializer( |
| 245 new VariableDeclaration.forValue( |
| 246 throwNoSuchMethodError( |
| 247 name.name, arguments, uri, charOffset, coreTypes, |
| 248 isSuper: isSuper))); |
| 249 } else if (isSuper) { |
| 250 result = new SuperInitializer(constructor, arguments); |
| 251 } else { |
| 252 result = new RedirectingInitializer(constructor, arguments); |
| 253 } |
| 254 return result |
| 255 ..fileOffset = charOffset; |
| 256 } |
| 257 |
| 258 Expression buildAssignment(Expression value, {bool voidContext: false}) { |
| 259 return internalError(""); |
| 260 } |
| 261 |
| 262 Expression buildNullAwareAssignment(Expression value, DartType type, |
| 263 {bool voidContext: false}) { |
| 264 return internalError(""); |
| 265 } |
| 266 |
| 267 Expression buildCompoundAssignment(Name binaryOperator, Expression value, |
| 268 {bool voidContext: false, Procedure interfaceTarget}) { |
| 269 return internalError(""); |
| 270 } |
| 271 |
| 272 Expression buildPrefixIncrement(Name binaryOperator, |
| 273 {bool voidContext: false, Procedure interfaceTarget}) { |
| 274 return internalError(""); |
| 275 } |
| 276 |
| 277 Expression buildPostfixIncrement(Name binaryOperator, |
| 278 {bool voidContext: false, Procedure interfaceTarget}) { |
| 279 return internalError(""); |
| 280 } |
| 281 |
| 282 toString() => "ThisAccessor($charOffset${isSuper ? ', super' : ''})"; |
| 283 } |
| 284 |
| 285 abstract class IncompleteSend extends BuilderAccessor { |
| 286 final BuilderHelper helper; |
| 287 |
| 288 final int charOffset; |
| 289 |
| 290 final Name name; |
| 291 |
| 292 IncompleteSend(this.helper, this.charOffset, this.name); |
| 293 |
| 294 withReceiver(Object receiver, {bool isNullAware}); |
| 295 } |
| 296 |
| 297 class IncompleteError extends IncompleteSend with CompileTimeErrorAccessor { |
| 298 final Object error; |
| 299 |
| 300 IncompleteError(BuilderHelper helper, int charOffset, this.error) |
| 301 : super(helper, charOffset, null); |
| 302 |
| 303 Expression buildError() { |
| 304 return helper.buildCompileTimeError(error, charOffset); |
| 305 } |
| 306 } |
| 307 |
| 308 class SendAccessor extends IncompleteSend { |
| 309 final Arguments arguments; |
| 310 |
| 311 SendAccessor(BuilderHelper helper, int charOffset, Name name, this.arguments) |
| 312 : super(helper, charOffset, name) { |
| 313 assert(arguments != null); |
| 314 } |
| 315 |
| 316 String get plainNameForRead => name.name; |
| 317 |
| 318 Expression buildSimpleRead() { |
| 319 return internalError("Unhandled"); |
| 320 } |
| 321 |
| 322 Expression buildAssignment(Expression value, {bool voidContext: false}) { |
| 323 return internalError("Unhandled"); |
| 324 } |
| 325 |
| 326 withReceiver(Object receiver, {bool isNullAware: false}) { |
| 327 if (receiver is TypeDeclarationBuilder) { |
| 328 /// `SomeType?.toString` is the same as `SomeType.toString`, not |
| 329 /// `(SomeType).toString`. |
| 330 isNullAware = false; |
| 331 } |
| 332 if (receiver is BuilderAccessor) { |
| 333 return receiver.buildPropertyAccess(this, isNullAware); |
| 334 } |
| 335 if (receiver is PrefixBuilder) { |
| 336 PrefixBuilder prefix = receiver; |
| 337 receiver = helper.builderToFirstExpression( |
| 338 prefix.exports[name.name], "${prefix.name}.${name.name}", charOffset); |
| 339 return helper.finishSend(receiver, arguments, charOffset); |
| 340 } |
| 341 Expression result; |
| 342 if (receiver is KernelClassBuilder) { |
| 343 Builder builder = receiver.findStaticBuilder(name.name); |
| 344 if (builder == null) { |
| 345 return buildThrowNoSuchMethodError(arguments); |
| 346 } |
| 347 if (builder.hasProblem) { |
| 348 result = helper.buildProblemExpression(builder, name.name); |
| 349 } else { |
| 350 Member target = builder.target; |
| 351 if (target != null) { |
| 352 if (target is Field) { |
| 353 result = buildMethodInvocation(new StaticGet(target), |
| 354 new Name("call"), arguments, charOffset, |
| 355 isNullAware: isNullAware); |
| 356 } else { |
| 357 result = helper.buildStaticInvocation(target, arguments); |
| 358 } |
| 359 } else { |
| 360 result = buildThrowNoSuchMethodError(arguments); |
| 361 } |
| 362 } |
| 363 } else { |
| 364 result = buildMethodInvocation(helper.toValue(receiver), name, |
| 365 arguments, charOffset, isNullAware: isNullAware); |
| 366 } |
| 367 return result..fileOffset = charOffset; |
| 368 } |
| 369 |
| 370 Expression buildNullAwareAssignment(Expression value, DartType type, |
| 371 {bool voidContext: false}) { |
| 372 return internalError(""); |
| 373 } |
| 374 |
| 375 Expression buildCompoundAssignment(Name binaryOperator, Expression value, |
| 376 {bool voidContext: false, Procedure interfaceTarget}) { |
| 377 return internalError(""); |
| 378 } |
| 379 |
| 380 Expression buildPrefixIncrement(Name binaryOperator, |
| 381 {bool voidContext: false, Procedure interfaceTarget}) { |
| 382 return internalError("Unhandled"); |
| 383 } |
| 384 |
| 385 Expression buildPostfixIncrement(Name binaryOperator, |
| 386 {bool voidContext: false, Procedure interfaceTarget}) { |
| 387 return internalError("Unhandled"); |
| 388 } |
| 389 |
| 390 Expression doInvocation(int charOffset, Arguments arguments) { |
| 391 return internalError("Unhandled"); |
| 392 } |
| 393 |
| 394 toString() => "SendAccessor($charOffset, $name, $arguments)"; |
| 395 } |
| 396 |
| 397 class IncompletePropertyAccessor extends IncompleteSend { |
| 398 IncompletePropertyAccessor(BuilderHelper helper, int charOffset, Name name) |
| 399 : super(helper, charOffset, name); |
| 400 |
| 401 String get plainNameForRead => name.name; |
| 402 |
| 403 Expression buildSimpleRead() => internalError("Unhandled"); |
| 404 |
| 405 Expression buildAssignment(Expression value, {bool voidContext: false}) { |
| 406 return internalError("Unhandled"); |
| 407 } |
| 408 |
| 409 withReceiver(Object receiver, {bool isNullAware: false}) { |
| 410 if (receiver is TypeDeclarationBuilder) { |
| 411 /// For reasons beyond comprehension, `SomeType?.toString` is the same as |
| 412 /// `SomeType.toString`, not `(SomeType).toString`. WTAF!?! |
| 413 // |
| 414 isNullAware = false; |
| 415 } |
| 416 if (receiver is BuilderAccessor) { |
| 417 return receiver.buildPropertyAccess(this, isNullAware); |
| 418 } |
| 419 if (receiver is PrefixBuilder) { |
| 420 PrefixBuilder prefix = receiver; |
| 421 return helper.builderToFirstExpression( |
| 422 prefix.exports[name.name], name.name, charOffset); |
| 423 } |
| 424 if (receiver is KernelClassBuilder) { |
| 425 Builder builder = receiver.findStaticBuilder(name.name); |
| 426 Member getter = builder?.target; |
| 427 Member setter; |
| 428 if (builder == null) { |
| 429 builder = receiver.findStaticBuilder(name.name, isSetter: true); |
| 430 if (builder == null) { |
| 431 return buildThrowNoSuchMethodError(null); |
| 432 } |
| 433 } |
| 434 if (builder.hasProblem) { |
| 435 return helper.buildProblemExpression(builder, name.name) |
| 436 ..fileOffset = charOffset; |
| 437 } |
| 438 if (getter is Field) { |
| 439 if (!getter.isFinal && !getter.isConst) { |
| 440 setter = getter; |
| 441 } |
| 442 } else if (getter is Procedure) { |
| 443 if (getter.isGetter) { |
| 444 builder = receiver.findStaticBuilder(name.name, isSetter: true); |
| 445 if (builder != null && !builder.hasProblem) { |
| 446 setter = builder.target; |
| 447 } |
| 448 } |
| 449 } |
| 450 if (getter == null) { |
| 451 return internalError("no getter for $name"); |
| 452 } |
| 453 return new StaticAccessor(helper, charOffset, getter, setter); |
| 454 } |
| 455 return PropertyAccessor.make(helper, charOffset, helper.toValue(receiver), |
| 456 name, null, null, isNullAware); |
| 457 } |
| 458 |
| 459 Expression buildNullAwareAssignment(Expression value, DartType type, |
| 460 {bool voidContext: false}) { |
| 461 return internalError("Unhandled"); |
| 462 } |
| 463 |
| 464 Expression buildCompoundAssignment(Name binaryOperator, Expression value, |
| 465 {bool voidContext: false, Procedure interfaceTarget}) { |
| 466 return internalError("Unhandled"); |
| 467 } |
| 468 |
| 469 Expression buildPrefixIncrement(Name binaryOperator, |
| 470 {bool voidContext: false, Procedure interfaceTarget}) { |
| 471 return internalError("Unhandled"); |
| 472 } |
| 473 |
| 474 Expression buildPostfixIncrement(Name binaryOperator, |
| 475 {bool voidContext: false, Procedure interfaceTarget}) { |
| 476 return internalError("Unhandled"); |
| 477 } |
| 478 |
| 479 Expression doInvocation(int charOffset, Arguments arguments) { |
| 480 return internalError("Unhandled"); |
| 481 } |
| 482 |
| 483 toString() => "IncompletePropertyAccessor($charOffset, $name)"; |
| 484 } |
| 485 |
| 486 class IndexAccessor extends kernel.IndexAccessor with BuilderAccessor { |
| 487 final BuilderHelper helper; |
| 488 |
| 489 final int charOffset; |
| 490 |
| 491 IndexAccessor.internal(this.helper, this.charOffset, Expression receiver, |
| 492 Expression index, Procedure getter, Procedure setter) |
| 493 : super.internal(receiver, index, getter, setter); |
| 494 |
| 495 String get plainNameForRead => "[]"; |
| 496 |
| 497 String get plainNameForWrite => "[]="; |
| 498 |
| 499 Expression doInvocation(int charOffset, Arguments arguments) { |
| 500 return buildMethodInvocation(buildSimpleRead(), new Name("call"), arguments, |
| 501 charOffset); |
| 502 } |
| 503 |
| 504 toString() => "IndexAccessor()"; |
| 505 |
| 506 static BuilderAccessor make(BuilderHelper helper, int charOffset, |
| 507 Expression receiver, Expression index, Procedure getter, |
| 508 Procedure setter) { |
| 509 if (receiver is ThisExpression) { |
| 510 return new ThisIndexAccessor(helper, charOffset, index, getter, setter); |
| 511 } else { |
| 512 return new IndexAccessor.internal(helper, charOffset, receiver, index, |
| 513 getter, setter); |
| 514 } |
| 515 } |
| 516 } |
| 517 |
| 518 class PropertyAccessor extends kernel.PropertyAccessor with BuilderAccessor { |
| 519 final BuilderHelper helper; |
| 520 |
| 521 final int charOffset; |
| 522 |
| 523 PropertyAccessor.internal(this.helper, this.charOffset, Expression receiver, |
| 524 Name name, Member getter, Member setter) |
| 525 : super.internal(receiver, name, getter, setter); |
| 526 |
| 527 String get plainNameForRead => name.name; |
| 528 |
| 529 bool get isThisPropertyAccessor => receiver is ThisExpression; |
| 530 |
| 531 Expression doInvocation(int charOffset, Arguments arguments) { |
| 532 return buildMethodInvocation(receiver, name, arguments, charOffset); |
| 533 } |
| 534 |
| 535 toString() => "PropertyAccessor()"; |
| 536 |
| 537 static BuilderAccessor make(BuilderHelper helper, int charOffset, |
| 538 Expression receiver, Name name, Member getter, Member setter, |
| 539 bool isNullAware) { |
| 540 if (receiver is ThisExpression) { |
| 541 return new ThisPropertyAccessor(helper, charOffset, name, getter, setter); |
| 542 } else { |
| 543 return isNullAware |
| 544 ? new NullAwarePropertyAccessor(helper, charOffset, receiver, name, |
| 545 getter, setter, null) |
| 546 : new PropertyAccessor.internal(helper, charOffset, receiver, name, |
| 547 getter, setter); |
| 548 } |
| 549 } |
| 550 } |
| 551 |
| 552 class StaticAccessor extends kernel.StaticAccessor with BuilderAccessor { |
| 553 final BuilderHelper helper; |
| 554 |
| 555 final int charOffset; |
| 556 |
| 557 StaticAccessor(this.helper, this.charOffset, Member readTarget, |
| 558 Member writeTarget) |
| 559 : super(readTarget, writeTarget) { |
| 560 assert(readTarget != null || writeTarget != null); |
| 561 } |
| 562 |
| 563 String get plainNameForRead => (readTarget ?? writeTarget).name.name; |
| 564 |
| 565 Expression doInvocation(int charOffset, Arguments arguments) { |
| 566 if (readTarget == null || isFieldOrGetter(readTarget)) { |
| 567 return buildMethodInvocation(buildSimpleRead(), new Name("call"), |
| 568 arguments, charOffset); |
| 569 } else { |
| 570 return helper.buildStaticInvocation(readTarget, arguments) |
| 571 ..fileOffset = charOffset; |
| 572 } |
| 573 } |
| 574 |
| 575 toString() => "StaticAccessor()"; |
| 576 } |
| 577 |
| 578 class SuperPropertyAccessor extends kernel.SuperPropertyAccessor |
| 579 with BuilderAccessor { |
| 580 final BuilderHelper helper; |
| 581 |
| 582 final int charOffset; |
| 583 |
| 584 SuperPropertyAccessor(this.helper, this.charOffset, Name name, Member getter, |
| 585 Member setter) |
| 586 : super(name, getter, setter); |
| 587 |
| 588 String get plainNameForRead => name.name; |
| 589 |
| 590 Expression doInvocation(int charOffset, Arguments arguments) { |
| 591 if (getter == null || isFieldOrGetter(getter)) { |
| 592 return buildMethodInvocation(buildSimpleRead(), new Name("call"), |
| 593 arguments, charOffset); |
| 594 } else { |
| 595 return new DirectMethodInvocation(new ThisExpression(), getter, arguments) |
| 596 ..fileOffset = charOffset; |
| 597 } |
| 598 } |
| 599 |
| 600 toString() => "SuperPropertyAccessor()"; |
| 601 } |
| 602 |
| 603 class ThisIndexAccessor extends kernel.ThisIndexAccessor with BuilderAccessor { |
| 604 final BuilderHelper helper; |
| 605 |
| 606 final int charOffset; |
| 607 |
| 608 ThisIndexAccessor(this.helper, this.charOffset, Expression index, |
| 609 Procedure getter, Procedure setter) |
| 610 : super(index, getter, setter); |
| 611 |
| 612 String get plainNameForRead => "[]"; |
| 613 |
| 614 String get plainNameForWrite => "[]="; |
| 615 |
| 616 Expression doInvocation(int charOffset, Arguments arguments) { |
| 617 return buildMethodInvocation(buildSimpleRead(), new Name("call"), arguments, |
| 618 charOffset); |
| 619 } |
| 620 |
| 621 toString() => "ThisIndexAccessor()"; |
| 622 } |
| 623 |
| 624 class ThisPropertyAccessor extends kernel.ThisPropertyAccessor |
| 625 with BuilderAccessor { |
| 626 final BuilderHelper helper; |
| 627 |
| 628 final int charOffset; |
| 629 |
| 630 ThisPropertyAccessor(this.helper, this.charOffset, Name name, Member getter, |
| 631 Member setter) |
| 632 : super(name, getter, setter); |
| 633 |
| 634 String get plainNameForRead => name.name; |
| 635 |
| 636 bool get isThisPropertyAccessor => true; |
| 637 |
| 638 Expression doInvocation(int charOffset, Arguments arguments) { |
| 639 Member interfaceTarget = getter; |
| 640 if (interfaceTarget is Field) { |
| 641 // TODO(ahe): In strong mode we should probably rewrite this to |
| 642 // `this.name.call(arguments)`. |
| 643 interfaceTarget = null; |
| 644 } |
| 645 return buildMethodInvocation(new ThisExpression(), name, arguments, |
| 646 charOffset); |
| 647 } |
| 648 |
| 649 toString() => "ThisPropertyAccessor()"; |
| 650 } |
| 651 |
| 652 class NullAwarePropertyAccessor extends kernel.NullAwarePropertyAccessor |
| 653 with BuilderAccessor { |
| 654 final BuilderHelper helper; |
| 655 |
| 656 final int charOffset; |
| 657 |
| 658 NullAwarePropertyAccessor(this.helper, this.charOffset, Expression receiver, |
| 659 Name name, Member getter, Member setter, DartType type) |
| 660 : super(receiver, name, getter, setter, type); |
| 661 |
| 662 String get plainNameForRead => name.name; |
| 663 |
| 664 Expression doInvocation(int charOffset, Arguments arguments) { |
| 665 return internalError("Not implemented yet."); |
| 666 } |
| 667 |
| 668 toString() => "NullAwarePropertyAccessor()"; |
| 669 } |
| 670 |
| 671 |
| 672 class VariableAccessor extends kernel.VariableAccessor |
| 673 with BuilderAccessor { |
| 674 final BuilderHelper helper; |
| 675 |
| 676 final int charOffset; |
| 677 |
| 678 VariableAccessor(this.helper, this.charOffset, VariableDeclaration variable, |
| 679 [DartType promotedType]) |
| 680 : super.internal(variable, promotedType); |
| 681 |
| 682 String get plainNameForRead => variable.name; |
| 683 |
| 684 Expression doInvocation(int charOffset, Arguments arguments) { |
| 685 return buildMethodInvocation(buildSimpleRead(), new Name("call"), arguments, |
| 686 charOffset); |
| 687 } |
| 688 |
| 689 toString() => "VariableAccessor()"; |
| 690 } |
| 691 |
| 692 Expression throwNoSuchMethodError(String name, Arguments arguments, Uri uri, |
| 693 int charOffset, CoreTypes coreTypes, |
| 694 {bool isSuper: false, isGetter: false, isSetter: false}) { |
| 695 print("$uri:$charOffset: method not found: '$name'."); |
| 696 Constructor constructor = coreTypes.getCoreClass( |
| 697 "dart:core", "NoSuchMethodError").constructors.first; |
| 698 return new Throw(new ConstructorInvocation( |
| 699 constructor, |
| 700 new Arguments(<Expression>[ |
| 701 new NullLiteral(), |
| 702 new SymbolLiteral(name), |
| 703 new ListLiteral(arguments.positional), |
| 704 new MapLiteral(arguments.named.map((arg) { |
| 705 return new MapEntry(new SymbolLiteral(arg.name), arg.value); |
| 706 }).toList()), |
| 707 new NullLiteral()]))); |
| 708 } |
| 709 |
| 710 bool isFieldOrGetter(Member member) { |
| 711 return member is Field || (member is Procedure && member.isGetter); |
| 712 } |
| 713 |
| 714 Expression buildMethodInvocation(Expression receiver, Name name, |
| 715 Arguments arguments, int charOffset, {bool isNullAware: false}) { |
| 716 if (isNullAware) { |
| 717 VariableDeclaration variable = new VariableDeclaration.forValue(receiver); |
| 718 return makeLet( |
| 719 variable, |
| 720 new ConditionalExpression( |
| 721 buildIsNull(new VariableGet(variable)), |
| 722 new NullLiteral(), |
| 723 new MethodInvocation(new VariableGet(variable), name, arguments) |
| 724 ..fileOffset = charOffset, |
| 725 const DynamicType())); |
| 726 } else { |
| 727 return new MethodInvocation(receiver, name, arguments) |
| 728 ..fileOffset = charOffset; |
| 729 } |
| 730 } |
OLD | NEW |