| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 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 | 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 library fasta.builder_accessors; | 5 library fasta.builder_accessors; |
| 6 | 6 |
| 7 export 'frontend_accessors.dart' show wrapInvalid; | 7 export 'frontend_accessors.dart' show wrapInvalid; |
| 8 | 8 |
| 9 import 'frontend_accessors.dart' show Accessor; | 9 import 'frontend_accessors.dart' show Accessor; |
| 10 | 10 |
| 11 import 'package:kernel/ast.dart'; | 11 import 'package:kernel/ast.dart'; |
| 12 | 12 |
| 13 import 'package:kernel/core_types.dart' show CoreTypes; | 13 import '../errors.dart' show internalError; |
| 14 | 14 |
| 15 import '../builder/scope.dart' show AccessErrorBuilder, ProblemBuilder; | 15 import '../builder/scope.dart' show AccessErrorBuilder, ProblemBuilder; |
| 16 | 16 |
| 17 import '../errors.dart' show internalError, printUnexpected; | |
| 18 | |
| 19 import 'frontend_accessors.dart' as kernel | 17 import 'frontend_accessors.dart' as kernel |
| 20 show | 18 show |
| 21 IndexAccessor, | 19 IndexAccessor, |
| 22 NullAwarePropertyAccessor, | 20 NullAwarePropertyAccessor, |
| 23 PropertyAccessor, | 21 PropertyAccessor, |
| 24 StaticAccessor, | 22 StaticAccessor, |
| 25 SuperIndexAccessor, | 23 SuperIndexAccessor, |
| 26 SuperPropertyAccessor, | 24 SuperPropertyAccessor, |
| 27 ThisIndexAccessor, | 25 ThisIndexAccessor, |
| 28 ThisPropertyAccessor, | 26 ThisPropertyAccessor, |
| 29 VariableAccessor; | 27 VariableAccessor; |
| 30 | 28 |
| 31 import 'frontend_accessors.dart' show buildIsNull, makeLet; | 29 import 'frontend_accessors.dart' show buildIsNull, makeLet; |
| 32 | 30 |
| 33 import 'kernel_builder.dart' | 31 import 'kernel_builder.dart' |
| 34 show Builder, KernelClassBuilder, PrefixBuilder, TypeDeclarationBuilder; | 32 show Builder, KernelClassBuilder, PrefixBuilder, TypeDeclarationBuilder; |
| 35 | 33 |
| 36 abstract class BuilderHelper { | 34 abstract class BuilderHelper { |
| 37 Uri get uri; | 35 Uri get uri; |
| 38 | 36 |
| 39 CoreTypes get coreTypes; | |
| 40 | |
| 41 Constructor lookupConstructor(Name name, {bool isSuper}); | 37 Constructor lookupConstructor(Name name, {bool isSuper}); |
| 42 | 38 |
| 43 Expression toSuperMethodInvocation(MethodInvocation node); | 39 Expression toSuperMethodInvocation(MethodInvocation node); |
| 44 | 40 |
| 45 Expression toValue(node); | 41 Expression toValue(node); |
| 46 | 42 |
| 47 Member lookupSuperMember(Name name, {bool isSetter: false}); | 43 Member lookupSuperMember(Name name, {bool isSetter: false}); |
| 48 | 44 |
| 49 builderToFirstExpression(Builder builder, String name, int charOffset); | 45 builderToFirstExpression(Builder builder, String name, int charOffset); |
| 50 | 46 |
| 51 finishSend(Object receiver, Arguments arguments, int charOffset); | 47 finishSend(Object receiver, Arguments arguments, int charOffset); |
| 52 | 48 |
| 53 Expression buildCompileTimeError(error, [int charOffset]); | 49 Expression buildCompileTimeError(error, [int charOffset]); |
| 54 | 50 |
| 55 Initializer buildCompileTimeErrorIntializer(error, [int charOffset]); | 51 Initializer buildCompileTimeErrorIntializer(error, [int charOffset]); |
| 56 | 52 |
| 57 Expression buildStaticInvocation(Procedure target, Arguments arguments); | 53 Expression buildStaticInvocation(Procedure target, Arguments arguments); |
| 58 | 54 |
| 59 Expression buildProblemExpression(ProblemBuilder builder, int charOffset); | 55 Expression buildProblemExpression(ProblemBuilder builder, int charOffset); |
| 56 |
| 57 Expression throwNoSuchMethodError( |
| 58 String name, Arguments arguments, int charOffset, |
| 59 {bool isSuper: false, isGetter: false, isSetter: false}); |
| 60 } | 60 } |
| 61 | 61 |
| 62 abstract class BuilderAccessor implements Accessor { | 62 abstract class BuilderAccessor implements Accessor { |
| 63 BuilderHelper get helper; | 63 BuilderHelper get helper; |
| 64 | 64 |
| 65 int get charOffset; | 65 int get charOffset; |
| 66 | 66 |
| 67 String get plainNameForRead; | 67 String get plainNameForRead; |
| 68 | 68 |
| 69 Uri get uri => helper.uri; | 69 Uri get uri => helper.uri; |
| 70 | 70 |
| 71 CoreTypes get coreTypes => helper.coreTypes; | |
| 72 | |
| 73 String get plainNameForWrite => plainNameForRead; | 71 String get plainNameForWrite => plainNameForRead; |
| 74 | 72 |
| 75 Expression buildForEffect() => buildSimpleRead(); | 73 Expression buildForEffect() => buildSimpleRead(); |
| 76 | 74 |
| 77 Initializer buildFieldInitializer( | 75 Initializer buildFieldInitializer( |
| 78 Map<String, FieldInitializer> initializers) { | 76 Map<String, FieldInitializer> initializers) { |
| 79 // TODO(ahe): This error message is really bad. | 77 // TODO(ahe): This error message is really bad. |
| 80 return helper.buildCompileTimeErrorIntializer( | 78 return helper.buildCompileTimeErrorIntializer( |
| 81 "Can't use $plainNameForRead here.", charOffset); | 79 "Can't use $plainNameForRead here.", charOffset); |
| 82 } | 80 } |
| 83 | 81 |
| 84 Expression makeInvalidRead() { | 82 Expression makeInvalidRead() { |
| 85 return throwNoSuchMethodError( | 83 return buildThrowNoSuchMethodError(new Arguments.empty(), isGetter: true); |
| 86 plainNameForRead, new Arguments.empty(), uri, charOffset, coreTypes, | |
| 87 isGetter: true); | |
| 88 } | 84 } |
| 89 | 85 |
| 90 Expression makeInvalidWrite(Expression value) { | 86 Expression makeInvalidWrite(Expression value) { |
| 91 return throwNoSuchMethodError(plainNameForWrite, | 87 return buildThrowNoSuchMethodError(new Arguments(<Expression>[value]), |
| 92 new Arguments(<Expression>[value]), uri, charOffset, coreTypes, | |
| 93 isSetter: true); | 88 isSetter: true); |
| 94 } | 89 } |
| 95 | 90 |
| 96 TreeNode doInvocation(int charOffset, Arguments arguments); | 91 /* Expression | BuilderAccessor */ doInvocation( |
| 92 int charOffset, Arguments arguments); |
| 97 | 93 |
| 98 buildPropertyAccess(IncompleteSend send, bool isNullAware) { | 94 /* Expression | BuilderAccessor */ buildPropertyAccess( |
| 95 IncompleteSend send, bool isNullAware) { |
| 99 if (send is SendAccessor) { | 96 if (send is SendAccessor) { |
| 100 return buildMethodInvocation( | 97 return buildMethodInvocation( |
| 101 buildSimpleRead(), send.name, send.arguments, send.charOffset, | 98 buildSimpleRead(), send.name, send.arguments, send.charOffset, |
| 102 isNullAware: isNullAware); | 99 isNullAware: isNullAware); |
| 103 } else { | 100 } else { |
| 104 return PropertyAccessor.make(helper, send.charOffset, buildSimpleRead(), | 101 return PropertyAccessor.make(helper, send.charOffset, buildSimpleRead(), |
| 105 send.name, null, null, isNullAware); | 102 send.name, null, null, isNullAware); |
| 106 } | 103 } |
| 107 } | 104 } |
| 108 | 105 |
| 109 Expression buildThrowNoSuchMethodError(Arguments arguments) { | 106 /* Expression | BuilderAccessor */ buildThrowNoSuchMethodError( |
| 110 bool isGetter = false; | 107 Arguments arguments, |
| 111 if (arguments == null) { | 108 {bool isSuper: false, |
| 112 arguments = new Arguments.empty(); | 109 isGetter: false, |
| 113 isGetter = true; | 110 isSetter: false, |
| 114 } | 111 String name, |
| 115 return throwNoSuchMethodError( | 112 int charOffset}) { |
| 116 plainNameForWrite, arguments, uri, charOffset, coreTypes, | 113 return helper.throwNoSuchMethodError( |
| 117 isGetter: isGetter); | 114 name ?? plainNameForWrite, arguments, charOffset ?? this.charOffset, |
| 115 isGetter: isGetter, isSetter: isSetter, isSuper: isSuper); |
| 118 } | 116 } |
| 119 | 117 |
| 120 bool get isThisPropertyAccessor => false; | 118 bool get isThisPropertyAccessor => false; |
| 121 } | 119 } |
| 122 | 120 |
| 123 abstract class CompileTimeErrorAccessor implements Accessor { | 121 abstract class CompileTimeErrorAccessor implements BuilderAccessor { |
| 124 Expression buildError(); | 122 Expression buildError(); |
| 125 | 123 |
| 126 Name get name => internalError("Unsupported operation."); | 124 Name get name => internalError("Unsupported operation."); |
| 127 | 125 |
| 128 String get plainNameForRead => name.name; | 126 String get plainNameForRead => name.name; |
| 129 | 127 |
| 130 withReceiver(Object receiver, {bool isNullAware}) => this; | 128 withReceiver(Object receiver, {bool isNullAware}) => this; |
| 131 | 129 |
| 132 Initializer buildFieldInitializer( | 130 Initializer buildFieldInitializer( |
| 133 Map<String, FieldInitializer> initializers) { | 131 Map<String, FieldInitializer> initializers) { |
| 134 return new LocalInitializer(new VariableDeclaration.forValue(buildError())); | 132 return new LocalInitializer(new VariableDeclaration.forValue(buildError())); |
| 135 } | 133 } |
| 136 | 134 |
| 137 doInvocation(int charOffset, Arguments arguments) => this; | 135 doInvocation(int charOffset, Arguments arguments) => this; |
| 138 | 136 |
| 139 buildPropertyAccess(IncompleteSend send, bool isNullAware) => this; | 137 buildPropertyAccess(IncompleteSend send, bool isNullAware) => this; |
| 140 | 138 |
| 141 buildThrowNoSuchMethodError(Arguments arguments) => this; | 139 buildThrowNoSuchMethodError(Arguments arguments, |
| 140 {bool isSuper: false, |
| 141 isGetter: false, |
| 142 isSetter: false, |
| 143 String name, |
| 144 int charOffset}) { |
| 145 return this; |
| 146 } |
| 142 | 147 |
| 143 Expression buildAssignment(Expression value, {bool voidContext: false}) { | 148 Expression buildAssignment(Expression value, {bool voidContext: false}) { |
| 144 return buildError(); | 149 return buildError(); |
| 145 } | 150 } |
| 146 | 151 |
| 147 Expression buildCompoundAssignment( | 152 Expression buildCompoundAssignment( |
| 148 Name binaryOperator, Expression value, int charOffset, | 153 Name binaryOperator, Expression value, int charOffset, |
| 149 {bool voidContext: false, Procedure interfaceTarget}) { | 154 {bool voidContext: false, Procedure interfaceTarget}) { |
| 150 return buildError(); | 155 return buildError(); |
| 151 } | 156 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 new ThisExpression(), new Name("call"), arguments, charOffset); | 239 new ThisExpression(), new Name("call"), arguments, charOffset); |
| 235 } | 240 } |
| 236 } | 241 } |
| 237 | 242 |
| 238 Initializer buildConstructorInitializer( | 243 Initializer buildConstructorInitializer( |
| 239 int charOffset, Name name, Arguments arguments) { | 244 int charOffset, Name name, Arguments arguments) { |
| 240 Constructor constructor = helper.lookupConstructor(name, isSuper: isSuper); | 245 Constructor constructor = helper.lookupConstructor(name, isSuper: isSuper); |
| 241 Initializer result; | 246 Initializer result; |
| 242 if (constructor == null) { | 247 if (constructor == null) { |
| 243 result = new LocalInitializer(new VariableDeclaration.forValue( | 248 result = new LocalInitializer(new VariableDeclaration.forValue( |
| 244 throwNoSuchMethodError( | 249 buildThrowNoSuchMethodError(arguments, |
| 245 name.name, arguments, uri, charOffset, coreTypes, | 250 isSuper: isSuper, name: name.name, charOffset: charOffset))); |
| 246 isSuper: isSuper))); | |
| 247 } else if (isSuper) { | 251 } else if (isSuper) { |
| 248 result = new SuperInitializer(constructor, arguments); | 252 result = new SuperInitializer(constructor, arguments); |
| 249 } else { | 253 } else { |
| 250 result = new RedirectingInitializer(constructor, arguments); | 254 result = new RedirectingInitializer(constructor, arguments); |
| 251 } | 255 } |
| 252 return result..fileOffset = charOffset; | 256 return result..fileOffset = charOffset; |
| 253 } | 257 } |
| 254 | 258 |
| 255 Expression buildAssignment(Expression value, {bool voidContext: false}) { | 259 Expression buildAssignment(Expression value, {bool voidContext: false}) { |
| 256 return buildAssignmentError(); | 260 return buildAssignmentError(); |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 } | 433 } |
| 430 if (receiver is PrefixBuilder) { | 434 if (receiver is PrefixBuilder) { |
| 431 PrefixBuilder prefix = receiver; | 435 PrefixBuilder prefix = receiver; |
| 432 return helper.builderToFirstExpression( | 436 return helper.builderToFirstExpression( |
| 433 prefix.exports[name.name], name.name, charOffset); | 437 prefix.exports[name.name], name.name, charOffset); |
| 434 } | 438 } |
| 435 if (receiver is KernelClassBuilder) { | 439 if (receiver is KernelClassBuilder) { |
| 436 Builder builder = receiver.findStaticBuilder(name.name, charOffset, uri); | 440 Builder builder = receiver.findStaticBuilder(name.name, charOffset, uri); |
| 437 if (builder == null) { | 441 if (builder == null) { |
| 438 // If we find a setter, [builder] is an [AccessErrorBuilder], not null. | 442 // If we find a setter, [builder] is an [AccessErrorBuilder], not null. |
| 439 return buildThrowNoSuchMethodError(null); | 443 return buildThrowNoSuchMethodError(new Arguments.empty(), |
| 444 isGetter: true); |
| 440 } | 445 } |
| 441 Builder setter; | 446 Builder setter; |
| 442 if (builder.isSetter) { | 447 if (builder.isSetter) { |
| 443 setter = builder; | 448 setter = builder; |
| 444 } else if (builder.isGetter) { | 449 } else if (builder.isGetter) { |
| 445 setter = receiver.findStaticBuilder(name.name, charOffset, uri, | 450 setter = receiver.findStaticBuilder(name.name, charOffset, uri, |
| 446 isSetter: true); | 451 isSetter: true); |
| 447 } else if (builder.isField && !builder.isFinal) { | 452 } else if (builder.isField && !builder.isFinal) { |
| 448 setter = builder; | 453 setter = builder; |
| 449 } | 454 } |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 721 Expression doInvocation(int charOffset, Arguments arguments) { | 726 Expression doInvocation(int charOffset, Arguments arguments) { |
| 722 // Normally the offset is at the start of the token, but in this case, | 727 // Normally the offset is at the start of the token, but in this case, |
| 723 // because we insert a '.call', we want it at the end instead. | 728 // because we insert a '.call', we want it at the end instead. |
| 724 return buildMethodInvocation(buildSimpleRead(), new Name("call"), arguments, | 729 return buildMethodInvocation(buildSimpleRead(), new Name("call"), arguments, |
| 725 charOffset + (variable.name?.length ?? 0)); | 730 charOffset + (variable.name?.length ?? 0)); |
| 726 } | 731 } |
| 727 | 732 |
| 728 toString() => "VariableAccessor()"; | 733 toString() => "VariableAccessor()"; |
| 729 } | 734 } |
| 730 | 735 |
| 731 Expression throwNoSuchMethodError(String name, Arguments arguments, Uri uri, | |
| 732 int charOffset, CoreTypes coreTypes, | |
| 733 {bool isSuper: false, isGetter: false, isSetter: false}) { | |
| 734 String errorName = name; | |
| 735 if (isSuper) { | |
| 736 errorName = "super.$name"; | |
| 737 } | |
| 738 if (isGetter) { | |
| 739 printUnexpected(uri, charOffset, "Getter not found: '$errorName'."); | |
| 740 } else if (isSetter) { | |
| 741 printUnexpected(uri, charOffset, "Setter not found: '$errorName'."); | |
| 742 } else { | |
| 743 printUnexpected(uri, charOffset, "Method not found: '$name'."); | |
| 744 } | |
| 745 Constructor constructor = | |
| 746 coreTypes.getClass("dart:core", "NoSuchMethodError").constructors.first; | |
| 747 return new Throw(new ConstructorInvocation( | |
| 748 constructor, | |
| 749 new Arguments(<Expression>[ | |
| 750 new NullLiteral(), | |
| 751 new SymbolLiteral(name), | |
| 752 new ListLiteral(arguments.positional), | |
| 753 new MapLiteral(arguments.named.map((arg) { | |
| 754 return new MapEntry(new SymbolLiteral(arg.name), arg.value); | |
| 755 }).toList()), | |
| 756 new NullLiteral() | |
| 757 ]))); | |
| 758 } | |
| 759 | |
| 760 bool isFieldOrGetter(Member member) { | 736 bool isFieldOrGetter(Member member) { |
| 761 return member is Field || (member is Procedure && member.isGetter); | 737 return member is Field || (member is Procedure && member.isGetter); |
| 762 } | 738 } |
| 763 | 739 |
| 764 Expression buildMethodInvocation( | 740 Expression buildMethodInvocation( |
| 765 Expression receiver, Name name, Arguments arguments, int charOffset, | 741 Expression receiver, Name name, Arguments arguments, int charOffset, |
| 766 {bool isNullAware: false}) { | 742 {bool isNullAware: false}) { |
| 767 if (isNullAware) { | 743 if (isNullAware) { |
| 768 VariableDeclaration variable = new VariableDeclaration.forValue(receiver); | 744 VariableDeclaration variable = new VariableDeclaration.forValue(receiver); |
| 769 return makeLet( | 745 return makeLet( |
| 770 variable, | 746 variable, |
| 771 new ConditionalExpression( | 747 new ConditionalExpression( |
| 772 buildIsNull(new VariableGet(variable)), | 748 buildIsNull(new VariableGet(variable)), |
| 773 new NullLiteral(), | 749 new NullLiteral(), |
| 774 new MethodInvocation(new VariableGet(variable), name, arguments) | 750 new MethodInvocation(new VariableGet(variable), name, arguments) |
| 775 ..fileOffset = charOffset, | 751 ..fileOffset = charOffset, |
| 776 const DynamicType())); | 752 const DynamicType())); |
| 777 } else { | 753 } else { |
| 778 return new MethodInvocation(receiver, name, arguments) | 754 return new MethodInvocation(receiver, name, arguments) |
| 779 ..fileOffset = charOffset; | 755 ..fileOffset = charOffset; |
| 780 } | 756 } |
| 781 } | 757 } |
| OLD | NEW |