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.body_builder; | 5 library fasta.body_builder; |
6 | 6 |
7 import '../parser/parser.dart' show FormalParameterType, optional; | 7 import '../parser/parser.dart' show FormalParameterType, optional; |
8 | 8 |
9 import '../parser/error_kind.dart' show ErrorKind; | 9 import '../parser/error_kind.dart' show ErrorKind; |
10 | 10 |
11 import '../parser/identifier_context.dart' show IdentifierContext; | 11 import '../parser/identifier_context.dart' show IdentifierContext; |
12 | 12 |
| 13 import 'package:front_end/src/fasta/builder/ast_factory.dart'; |
| 14 import 'package:front_end/src/fasta/kernel/ast_factory.dart' as kernel; |
| 15 import 'package:front_end/src/fasta/type_inference/local_type_inferrer.dart'; |
| 16 import 'shadow_ast.dart' as shadow; |
13 import 'package:kernel/ast.dart'; | 17 import 'package:kernel/ast.dart'; |
14 | 18 |
15 import 'package:kernel/clone.dart' show CloneVisitor; | 19 import 'package:kernel/clone.dart' show CloneVisitor; |
16 | 20 |
17 import 'package:kernel/transformations/flags.dart' show TransformerFlag; | 21 import 'package:kernel/transformations/flags.dart' show TransformerFlag; |
18 | 22 |
19 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy; | 23 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy; |
20 | 24 |
21 import 'package:kernel/core_types.dart' show CoreTypes; | 25 import 'package:kernel/core_types.dart' show CoreTypes; |
22 | 26 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 CloneVisitor cloner; | 125 CloneVisitor cloner; |
122 | 126 |
123 bool constantExpressionRequired = false; | 127 bool constantExpressionRequired = false; |
124 | 128 |
125 DartType currentLocalVariableType; | 129 DartType currentLocalVariableType; |
126 | 130 |
127 // Using non-null value to initialize this field based on performance advice | 131 // Using non-null value to initialize this field based on performance advice |
128 // from VM engineers. TODO(ahe): Does this still apply? | 132 // from VM engineers. TODO(ahe): Does this still apply? |
129 int currentLocalVariableModifiers = -1; | 133 int currentLocalVariableModifiers = -1; |
130 | 134 |
| 135 final AstFactory _ast = new kernel.AstFactory(); |
| 136 |
| 137 final LocalTypeInferrer _typeInferrer; |
| 138 |
| 139 OldFunctionContext _functionContext; |
| 140 |
131 BodyBuilder( | 141 BodyBuilder( |
132 KernelLibraryBuilder library, | 142 KernelLibraryBuilder library, |
133 this.member, | 143 this.member, |
134 Scope scope, | 144 Scope scope, |
135 this.formalParameterScope, | 145 this.formalParameterScope, |
136 this.hierarchy, | 146 this.hierarchy, |
137 this.coreTypes, | 147 CoreTypes coreTypes, |
138 this.classBuilder, | 148 this.classBuilder, |
139 this.isInstanceMember, | 149 this.isInstanceMember, |
140 this.uri) | 150 this.uri) |
141 : enclosingScope = scope, | 151 : coreTypes = coreTypes, |
| 152 enclosingScope = scope, |
142 library = library, | 153 library = library, |
143 isDartLibrary = library.uri.scheme == "dart", | 154 isDartLibrary = library.uri.scheme == "dart", |
| 155 // TODO(paulberry): put this behind a flag. |
| 156 _typeInferrer = new LocalTypeInferrer(coreTypes), |
144 super(scope); | 157 super(scope); |
145 | 158 |
146 bool get hasParserError => recoverableErrors.isNotEmpty; | 159 bool get hasParserError => recoverableErrors.isNotEmpty; |
147 | 160 |
148 bool get inConstructor { | 161 bool get inConstructor { |
149 return functionNestingLevel == 0 && member is KernelConstructorBuilder; | 162 return functionNestingLevel == 0 && member is KernelConstructorBuilder; |
150 } | 163 } |
151 | 164 |
152 bool get isInstanceContext { | 165 bool get isInstanceContext { |
153 return isInstanceMember || member is KernelConstructorBuilder; | 166 return isInstanceMember || member is KernelConstructorBuilder; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 } else { | 220 } else { |
208 return internalError("Unhandled: ${node.runtimeType}"); | 221 return internalError("Unhandled: ${node.runtimeType}"); |
209 } | 222 } |
210 } | 223 } |
211 | 224 |
212 Expression toEffect(Object node) { | 225 Expression toEffect(Object node) { |
213 if (node is BuilderAccessor) return node.buildForEffect(); | 226 if (node is BuilderAccessor) return node.buildForEffect(); |
214 return toValue(node); | 227 return toValue(node); |
215 } | 228 } |
216 | 229 |
217 List<Expression> popListForValue(int n) { | 230 List<shadow.Expression> popListForValue(int n) { |
218 List<Expression> list = | 231 List<shadow.Expression> list = |
219 new List<Expression>.filled(n, null, growable: true); | 232 new List<shadow.Expression>.filled(n, null, growable: true); |
220 for (int i = n - 1; i >= 0; i--) { | 233 for (int i = n - 1; i >= 0; i--) { |
221 list[i] = popForValue(); | 234 list[i] = popForValue(); |
222 } | 235 } |
223 return list; | 236 return list; |
224 } | 237 } |
225 | 238 |
226 List<Expression> popListForEffect(int n) { | 239 List<Expression> popListForEffect(int n) { |
227 List<Expression> list = | 240 List<Expression> list = |
228 new List<Expression>.filled(n, null, growable: true); | 241 new List<Expression>.filled(n, null, growable: true); |
229 for (int i = n - 1; i >= 0; i--) { | 242 for (int i = n - 1; i >= 0; i--) { |
230 list[i] = popForEffect(); | 243 list[i] = popForEffect(); |
231 } | 244 } |
232 return list; | 245 return list; |
233 } | 246 } |
234 | 247 |
235 Block popBlock(int count, int charOffset) { | 248 shadow.Block popBlock(int count, int charOffset) { |
236 List<dynamic /*Statement | List<Statement>*/ > statements = | 249 List<dynamic /*Statement | List<Statement>*/ > statements = |
237 popList(count) ?? <Statement>[]; | 250 popList(count) ?? <Statement>[]; |
238 List<Statement> copy; | 251 List<Statement> copy; |
239 for (int i = 0; i < statements.length; i++) { | 252 for (int i = 0; i < statements.length; i++) { |
240 var statement = statements[i]; | 253 var statement = statements[i]; |
241 if (statement is List) { | 254 if (statement is List) { |
242 copy ??= new List<Statement>.from(statements.getRange(0, i)); | 255 copy ??= new List<Statement>.from(statements.getRange(0, i)); |
243 // TODO(sigmund): remove this assignment (issue #28651) | 256 // TODO(sigmund): remove this assignment (issue #28651) |
244 Iterable subStatements = statement; | 257 Iterable subStatements = statement; |
245 copy.addAll(subStatements); | 258 copy.addAll(subStatements); |
246 } else if (copy != null) { | 259 } else if (copy != null) { |
247 copy.add(statement); | 260 copy.add(statement); |
248 } | 261 } |
249 } | 262 } |
250 return new Block(copy ?? statements)..fileOffset = charOffset; | 263 return _ast.block(copy ?? statements, charOffset); |
251 } | 264 } |
252 | 265 |
253 Statement popStatementIfNotNull(Object value) { | 266 Statement popStatementIfNotNull(Object value) { |
254 return value == null ? null : popStatement(); | 267 return value == null ? null : popStatement(); |
255 } | 268 } |
256 | 269 |
257 Statement popStatement() { | 270 Statement popStatement() { |
258 var statement = pop(); | 271 var statement = pop(); |
259 if (statement is List) { | 272 if (statement is List) { |
260 return new Block(new List<Statement>.from(statement)); | 273 return new Block(new List<Statement>.from(statement)); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 void handleNoInitializers() { | 450 void handleNoInitializers() { |
438 debugEvent("NoInitializers"); | 451 debugEvent("NoInitializers"); |
439 } | 452 } |
440 | 453 |
441 @override | 454 @override |
442 void endInitializers(int count, Token beginToken, Token endToken) { | 455 void endInitializers(int count, Token beginToken, Token endToken) { |
443 debugEvent("Initializers"); | 456 debugEvent("Initializers"); |
444 } | 457 } |
445 | 458 |
446 @override | 459 @override |
447 void finishFunction( | 460 void finishFunction(FormalParameters formals, AsyncMarker asyncModifier, |
448 FormalParameters formals, AsyncMarker asyncModifier, Statement body) { | 461 shadow.Statement body) { |
449 debugEvent("finishFunction"); | 462 debugEvent("finishFunction"); |
450 KernelFunctionBuilder builder = member; | 463 KernelFunctionBuilder builder = member; |
451 if (builder is KernelConstructorBuilder) { | 464 if (builder is KernelConstructorBuilder) { |
452 if (asyncModifier != AsyncMarker.Sync) { | 465 if (asyncModifier != AsyncMarker.Sync) { |
453 // TODO(ahe): Change this to a null check. | 466 // TODO(ahe): Change this to a null check. |
454 addCompileTimeError(body?.fileOffset, | 467 addCompileTimeError(body?.fileOffset, |
455 "Can't be marked as ${asyncModifier}: ${builder.name}"); | 468 "Can't be marked as ${asyncModifier}: ${builder.name}"); |
456 } | 469 } |
457 } else if (builder is KernelProcedureBuilder) { | 470 } else if (builder is KernelProcedureBuilder) { |
458 builder.asyncModifier = asyncModifier; | 471 builder.asyncModifier = asyncModifier; |
459 } else { | 472 } else { |
460 internalError("Unhandled: ${builder.runtimeType}"); | 473 internalError("Unhandled: ${builder.runtimeType}"); |
461 } | 474 } |
| 475 _typeInferrer.inferBody(body); |
462 builder.body = body; | 476 builder.body = body; |
463 if (formals?.optional != null) { | 477 if (formals?.optional != null) { |
464 Iterator<FormalParameterBuilder> formalBuilders = | 478 Iterator<FormalParameterBuilder> formalBuilders = |
465 builder.formals.skip(formals.required.length).iterator; | 479 builder.formals.skip(formals.required.length).iterator; |
466 for (VariableDeclaration parameter in formals.optional.formals) { | 480 for (VariableDeclaration parameter in formals.optional.formals) { |
467 bool hasMore = formalBuilders.moveNext(); | 481 bool hasMore = formalBuilders.moveNext(); |
468 assert(hasMore); | 482 assert(hasMore); |
469 VariableDeclaration realParameter = formalBuilders.current.target; | 483 VariableDeclaration realParameter = formalBuilders.current.target; |
470 Expression initializer = parameter.initializer ?? new NullLiteral(); | 484 Expression initializer = parameter.initializer ?? new NullLiteral(); |
471 realParameter.initializer = initializer..parent = realParameter; | 485 realParameter.initializer = initializer..parent = realParameter; |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
914 expressions.add(part); | 928 expressions.add(part); |
915 } | 929 } |
916 } | 930 } |
917 } | 931 } |
918 push(new StringConcatenation(expressions ?? parts)); | 932 push(new StringConcatenation(expressions ?? parts)); |
919 } | 933 } |
920 | 934 |
921 @override | 935 @override |
922 void handleLiteralInt(Token token) { | 936 void handleLiteralInt(Token token) { |
923 debugEvent("LiteralInt"); | 937 debugEvent("LiteralInt"); |
924 push( | 938 push(_ast.intLiteral(int.parse(token.lexeme), token.charOffset)); |
925 new IntLiteral(int.parse(token.lexeme))..fileOffset = token.charOffset); | |
926 } | 939 } |
927 | 940 |
928 @override | 941 @override |
929 void handleEmptyFunctionBody(Token semicolon) { | 942 void handleEmptyFunctionBody(Token semicolon) { |
930 debugEvent("ExpressionFunctionBody"); | 943 debugEvent("ExpressionFunctionBody"); |
931 endBlockFunctionBody(0, null, semicolon); | 944 endBlockFunctionBody(0, null, semicolon); |
932 } | 945 } |
933 | 946 |
934 @override | 947 @override |
935 void handleExpressionFunctionBody(Token arrowToken, Token endToken) { | 948 void handleExpressionFunctionBody(Token arrowToken, Token endToken) { |
936 debugEvent("ExpressionFunctionBody"); | 949 debugEvent("ExpressionFunctionBody"); |
937 endReturnStatement(true, arrowToken.next, endToken); | 950 endReturnStatement(true, arrowToken.next, endToken); |
938 } | 951 } |
939 | 952 |
940 @override | 953 @override |
941 void endReturnStatement( | 954 void endReturnStatement( |
942 bool hasExpression, Token beginToken, Token endToken) { | 955 bool hasExpression, Token beginToken, Token endToken) { |
943 debugEvent("ReturnStatement"); | 956 debugEvent("ReturnStatement"); |
944 Expression expression = hasExpression ? popForValue() : null; | 957 shadow.Expression expression = hasExpression ? popForValue() : null; |
945 if (expression != null && inConstructor) { | 958 if (expression != null && inConstructor) { |
946 push(buildCompileTimeErrorStatement( | 959 push(buildCompileTimeErrorStatement( |
947 "Can't return from a constructor.", beginToken.charOffset)); | 960 "Can't return from a constructor.", beginToken.charOffset)); |
948 } else { | 961 } else { |
949 push(new ReturnStatement(expression)..fileOffset = beginToken.charOffset); | 962 push(_ast.returnStatement(expression, beginToken.charOffset)); |
| 963 _typeInferrer.recordReturnStatement(_functionContext, expression); |
950 } | 964 } |
951 } | 965 } |
952 | 966 |
953 @override | 967 @override |
954 void endIfStatement(Token ifToken, Token elseToken) { | 968 void endIfStatement(Token ifToken, Token elseToken) { |
955 Statement elsePart = popStatementIfNotNull(elseToken); | 969 Statement elsePart = popStatementIfNotNull(elseToken); |
956 Statement thenPart = popStatement(); | 970 Statement thenPart = popStatement(); |
957 Expression condition = popForValue(); | 971 Expression condition = popForValue(); |
958 push(new IfStatement(condition, thenPart, elsePart)); | 972 push(new IfStatement(condition, thenPart, elsePart)); |
959 } | 973 } |
960 | 974 |
961 @override | 975 @override |
962 void endVariableInitializer(Token assignmentOperator) { | 976 void endVariableInitializer(Token assignmentOperator) { |
963 debugEvent("VariableInitializer"); | 977 debugEvent("VariableInitializer"); |
964 assert(assignmentOperator.stringValue == "="); | 978 assert(assignmentOperator.stringValue == "="); |
965 pushNewLocalVariable(popForValue(), | 979 pushNewLocalVariable(popForValue(), |
966 equalsCharOffset: assignmentOperator.charOffset); | 980 equalsCharOffset: assignmentOperator.charOffset); |
967 } | 981 } |
968 | 982 |
969 @override | 983 @override |
970 void handleNoVariableInitializer(Token token) { | 984 void handleNoVariableInitializer(Token token) { |
971 debugEvent("NoVariableInitializer"); | 985 debugEvent("NoVariableInitializer"); |
972 pushNewLocalVariable(null); | 986 pushNewLocalVariable(null); |
973 } | 987 } |
974 | 988 |
975 void pushNewLocalVariable(Expression initializer, | 989 void pushNewLocalVariable(shadow.Expression initializer, |
976 {int equalsCharOffset: TreeNode.noOffset}) { | 990 {int equalsCharOffset: TreeNode.noOffset}) { |
977 Identifier identifier = pop(); | 991 Identifier identifier = pop(); |
978 assert(currentLocalVariableModifiers != -1); | 992 assert(currentLocalVariableModifiers != -1); |
979 bool isConst = (currentLocalVariableModifiers & constMask) != 0; | 993 bool isConst = (currentLocalVariableModifiers & constMask) != 0; |
980 bool isFinal = (currentLocalVariableModifiers & finalMask) != 0; | 994 bool isFinal = (currentLocalVariableModifiers & finalMask) != 0; |
981 assert(isConst == constantExpressionRequired); | 995 assert(isConst == constantExpressionRequired); |
982 push(new VariableDeclaration(identifier.name, | 996 var variable = _ast.variableDeclaration(identifier.name, |
983 initializer: initializer, | 997 initializer: initializer, |
984 type: currentLocalVariableType ?? const DynamicType(), | 998 type: currentLocalVariableType, |
985 isFinal: isFinal, | 999 isFinal: isFinal, |
986 isConst: isConst)..fileEqualsOffset = equalsCharOffset); | 1000 isConst: isConst, |
| 1001 charOffset: equalsCharOffset); |
| 1002 _typeInferrer.finishVariableDeclaration( |
| 1003 currentLocalVariableType, initializer, variable); |
| 1004 push(variable); |
987 } | 1005 } |
988 | 1006 |
989 @override | 1007 @override |
990 void endFieldInitializer(Token assignmentOperator) { | 1008 void endFieldInitializer(Token assignmentOperator) { |
991 debugEvent("FieldInitializer"); | 1009 debugEvent("FieldInitializer"); |
992 assert(assignmentOperator.stringValue == "="); | 1010 assert(assignmentOperator.stringValue == "="); |
993 push(popForValue()); | 1011 push(popForValue()); |
994 } | 1012 } |
995 | 1013 |
996 @override | 1014 @override |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1136 void endAwaitExpression(Token beginToken, Token endToken) { | 1154 void endAwaitExpression(Token beginToken, Token endToken) { |
1137 debugEvent("AwaitExpression"); | 1155 debugEvent("AwaitExpression"); |
1138 push( | 1156 push( |
1139 new AwaitExpression(popForValue())..fileOffset = beginToken.charOffset); | 1157 new AwaitExpression(popForValue())..fileOffset = beginToken.charOffset); |
1140 } | 1158 } |
1141 | 1159 |
1142 @override | 1160 @override |
1143 void handleAsyncModifier(Token asyncToken, Token starToken) { | 1161 void handleAsyncModifier(Token asyncToken, Token starToken) { |
1144 debugEvent("AsyncModifier"); | 1162 debugEvent("AsyncModifier"); |
1145 push(asyncMarkerFromTokens(asyncToken, starToken)); | 1163 push(asyncMarkerFromTokens(asyncToken, starToken)); |
| 1164 _functionContext?.recordAsyncModifier(asyncToken != null); |
1146 } | 1165 } |
1147 | 1166 |
1148 @override | 1167 @override |
1149 void handleLiteralList( | 1168 void handleLiteralList( |
1150 int count, Token beginToken, Token constKeyword, Token endToken) { | 1169 int count, Token beginToken, Token constKeyword, Token endToken) { |
1151 debugEvent("LiteralList"); | 1170 debugEvent("LiteralList"); |
1152 List<Expression> expressions = popListForValue(count); | 1171 List<shadow.Expression> expressions = popListForValue(count); |
1153 List<DartType> typeArguments = pop(); | 1172 List<DartType> typeArguments = pop(); |
1154 DartType typeArgument = const DynamicType(); | 1173 DartType typeArgument; |
1155 if (typeArguments != null) { | 1174 if (typeArguments != null) { |
1156 typeArgument = typeArguments.first; | 1175 typeArgument = typeArguments.first; |
1157 if (typeArguments.length > 1) { | 1176 if (typeArguments.length > 1) { |
1158 typeArgument = const DynamicType(); | 1177 typeArgument = null; |
1159 warning( | 1178 warning( |
1160 "Too many type arguments on List literal.", beginToken.charOffset); | 1179 "Too many type arguments on List literal.", beginToken.charOffset); |
1161 } | 1180 } |
1162 } | 1181 } |
1163 push(new ListLiteral(expressions, | 1182 push(_ast.listLiteral(expressions, typeArgument, constKeyword != null, |
1164 typeArgument: typeArgument, isConst: constKeyword != null) | 1183 constKeyword?.charOffset ?? beginToken.charOffset)); |
1165 ..fileOffset = constKeyword?.charOffset ?? beginToken.charOffset); | |
1166 } | 1184 } |
1167 | 1185 |
1168 @override | 1186 @override |
1169 void handleLiteralBool(Token token) { | 1187 void handleLiteralBool(Token token) { |
1170 debugEvent("LiteralBool"); | 1188 debugEvent("LiteralBool"); |
1171 bool value = optional("true", token); | 1189 bool value = optional("true", token); |
1172 assert(value || optional("false", token)); | 1190 assert(value || optional("false", token)); |
1173 push(new BoolLiteral(value)..fileOffset = token.charOffset); | 1191 push(new BoolLiteral(value)..fileOffset = token.charOffset); |
1174 } | 1192 } |
1175 | 1193 |
1176 @override | 1194 @override |
1177 void handleLiteralDouble(Token token) { | 1195 void handleLiteralDouble(Token token) { |
1178 debugEvent("LiteralDouble"); | 1196 debugEvent("LiteralDouble"); |
1179 push(new DoubleLiteral(double.parse(token.lexeme)) | 1197 push(new DoubleLiteral(double.parse(token.lexeme)) |
1180 ..fileOffset = token.charOffset); | 1198 ..fileOffset = token.charOffset); |
1181 } | 1199 } |
1182 | 1200 |
1183 @override | 1201 @override |
1184 void handleLiteralNull(Token token) { | 1202 void handleLiteralNull(Token token) { |
1185 debugEvent("LiteralNull"); | 1203 debugEvent("LiteralNull"); |
1186 push(new NullLiteral()..fileOffset = token.charOffset); | 1204 push(_ast.nullLiteral(token.charOffset)); |
1187 } | 1205 } |
1188 | 1206 |
1189 @override | 1207 @override |
1190 void handleLiteralMap( | 1208 void handleLiteralMap( |
1191 int count, Token beginToken, Token constKeyword, Token endToken) { | 1209 int count, Token beginToken, Token constKeyword, Token endToken) { |
1192 debugEvent("LiteralMap"); | 1210 debugEvent("LiteralMap"); |
1193 List<MapEntry> entries = popList(count) ?? <MapEntry>[]; | 1211 List<MapEntry> entries = popList(count) ?? <MapEntry>[]; |
1194 List<DartType> typeArguments = pop(); | 1212 List<DartType> typeArguments = pop(); |
1195 DartType keyType = const DynamicType(); | 1213 DartType keyType = const DynamicType(); |
1196 DartType valueType = const DynamicType(); | 1214 DartType valueType = const DynamicType(); |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1398 if (!inConstructor) { | 1416 if (!inConstructor) { |
1399 addCompileTimeError(thisKeyword.charOffset, | 1417 addCompileTimeError(thisKeyword.charOffset, |
1400 "'this' parameters can only be used on constructors."); | 1418 "'this' parameters can only be used on constructors."); |
1401 thisKeyword = null; | 1419 thisKeyword = null; |
1402 } | 1420 } |
1403 } | 1421 } |
1404 Identifier name = pop(); | 1422 Identifier name = pop(); |
1405 DartType type = pop(); | 1423 DartType type = pop(); |
1406 pop(); // Modifiers. | 1424 pop(); // Modifiers. |
1407 ignore(Unhandled.Metadata); | 1425 ignore(Unhandled.Metadata); |
1408 VariableDeclaration variable; | 1426 shadow.VariableDeclaration variable; |
1409 if (!inCatchClause && functionNestingLevel == 0) { | 1427 if (!inCatchClause && functionNestingLevel == 0) { |
1410 dynamic builder = formalParameterScope.lookup(name.name, charOffset, uri); | 1428 dynamic builder = formalParameterScope.lookup(name.name, charOffset, uri); |
1411 if (builder == null) { | 1429 if (builder == null) { |
1412 if (thisKeyword == null) { | 1430 if (thisKeyword == null) { |
1413 internalError("Internal error: formal missing for '${name.name}'"); | 1431 internalError("Internal error: formal missing for '${name.name}'"); |
1414 } else { | 1432 } else { |
1415 addCompileTimeError(thisKeyword.charOffset, | 1433 addCompileTimeError(thisKeyword.charOffset, |
1416 "'${name.name}' isn't a field in this class."); | 1434 "'${name.name}' isn't a field in this class."); |
1417 thisKeyword = null; | 1435 thisKeyword = null; |
1418 } | 1436 } |
1419 } else if (thisKeyword == null) { | 1437 } else if (thisKeyword == null) { |
1420 variable = builder.build(library); | 1438 variable = builder.build(library); |
1421 variable.initializer = name.initializer; | 1439 variable.initializer = name.initializer; |
1422 } else if (builder.isField && builder.parent == classBuilder) { | 1440 } else if (builder.isField && builder.parent == classBuilder) { |
1423 FieldBuilder field = builder; | 1441 FieldBuilder field = builder; |
1424 if (type != null) { | 1442 if (type != null) { |
1425 nit("Ignoring type on 'this' parameter '${name.name}'.", | 1443 nit("Ignoring type on 'this' parameter '${name.name}'.", |
1426 thisKeyword.charOffset); | 1444 thisKeyword.charOffset); |
1427 } | 1445 } |
1428 type = field.target.type ?? const DynamicType(); | 1446 type = field.target.type ?? const DynamicType(); |
1429 variable = new VariableDeclaration(name.name, | 1447 variable = _ast.variableDeclaration(name.name, |
1430 type: type, initializer: name.initializer); | 1448 type: type, |
| 1449 initializer: name.initializer as shadow.Expression, |
| 1450 charOffset: name.fileOffset); |
1431 } else { | 1451 } else { |
1432 addCompileTimeError( | 1452 addCompileTimeError( |
1433 name.fileOffset, "'${name.name}' isn't a field in this class."); | 1453 name.fileOffset, "'${name.name}' isn't a field in this class."); |
1434 } | 1454 } |
1435 } | 1455 } |
1436 variable ??= new VariableDeclaration(name.name, | 1456 variable ??= _ast.variableDeclaration(name.name, |
1437 type: type ?? const DynamicType(), | 1457 type: type, |
1438 initializer: name.initializer)..fileOffset = name.fileOffset; | 1458 initializer: name.initializer as shadow.Expression, |
| 1459 charOffset: name.fileOffset); |
1439 push(variable); | 1460 push(variable); |
1440 } | 1461 } |
1441 | 1462 |
1442 @override | 1463 @override |
1443 void endOptionalFormalParameters( | 1464 void endOptionalFormalParameters( |
1444 int count, Token beginToken, Token endToken) { | 1465 int count, Token beginToken, Token endToken) { |
1445 debugEvent("OptionalFormalParameters"); | 1466 debugEvent("OptionalFormalParameters"); |
1446 FormalParameterType kind = optional("{", beginToken) | 1467 FormalParameterType kind = optional("{", beginToken) |
1447 ? FormalParameterType.NAMED | 1468 ? FormalParameterType.NAMED |
1448 : FormalParameterType.POSITIONAL; | 1469 : FormalParameterType.POSITIONAL; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1494 } | 1515 } |
1495 FormalParameters formals = new FormalParameters( | 1516 FormalParameters formals = new FormalParameters( |
1496 popList(count) ?? <VariableDeclaration>[], | 1517 popList(count) ?? <VariableDeclaration>[], |
1497 optional, | 1518 optional, |
1498 beginToken.charOffset); | 1519 beginToken.charOffset); |
1499 push(formals); | 1520 push(formals); |
1500 if (inCatchClause || functionNestingLevel != 0) { | 1521 if (inCatchClause || functionNestingLevel != 0) { |
1501 enterLocalScope(formals.computeFormalParameterScope( | 1522 enterLocalScope(formals.computeFormalParameterScope( |
1502 scope, member ?? classBuilder ?? library)); | 1523 scope, member ?? classBuilder ?? library)); |
1503 } | 1524 } |
| 1525 formals.recordTypeInferenceTo(_functionContext); |
1504 } | 1526 } |
1505 | 1527 |
1506 @override | 1528 @override |
1507 void beginCatchClause(Token token) { | 1529 void beginCatchClause(Token token) { |
1508 debugEvent("beginCatchClause"); | 1530 debugEvent("beginCatchClause"); |
1509 inCatchClause = true; | 1531 inCatchClause = true; |
1510 } | 1532 } |
1511 | 1533 |
1512 @override | 1534 @override |
1513 void endCatchClause(Token token) { | 1535 void endCatchClause(Token token) { |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1871 VariableDeclaration variable = | 1893 VariableDeclaration variable = |
1872 new VariableDeclaration(name.name, isFinal: true); | 1894 new VariableDeclaration(name.name, isFinal: true); |
1873 push(new FunctionDeclaration( | 1895 push(new FunctionDeclaration( |
1874 variable, new FunctionNode(new InvalidStatement())) | 1896 variable, new FunctionNode(new InvalidStatement())) |
1875 ..fileOffset = beginToken.charOffset); | 1897 ..fileOffset = beginToken.charOffset); |
1876 scope[variable.name] = new KernelVariableBuilder( | 1898 scope[variable.name] = new KernelVariableBuilder( |
1877 variable, member ?? classBuilder ?? library, uri); | 1899 variable, member ?? classBuilder ?? library, uri); |
1878 enterLocalScope(); | 1900 enterLocalScope(); |
1879 } | 1901 } |
1880 | 1902 |
1881 void enterFunction() { | 1903 void enterFunction(bool isNamed) { |
1882 debugEvent("enterFunction"); | 1904 debugEvent("enterFunction"); |
1883 functionNestingLevel++; | 1905 functionNestingLevel++; |
1884 push(switchScope ?? NullValue.SwitchScope); | 1906 push(switchScope ?? NullValue.SwitchScope); |
1885 switchScope = null; | 1907 switchScope = null; |
| 1908 _functionContext = _typeInferrer.nestFunctionContext(_functionContext); |
1886 } | 1909 } |
1887 | 1910 |
1888 void exitFunction() { | 1911 void exitFunction() { |
1889 debugEvent("exitFunction"); | 1912 debugEvent("exitFunction"); |
1890 functionNestingLevel--; | 1913 functionNestingLevel--; |
1891 switchScope = pop(); | 1914 switchScope = pop(); |
1892 } | 1915 } |
1893 | 1916 |
1894 @override | 1917 @override |
1895 void beginFunction(Token token) { | 1918 void beginFunction(Token token) { |
1896 debugEvent("beginFunction"); | 1919 debugEvent("beginFunction"); |
1897 enterFunction(); | 1920 enterFunction(true); |
1898 } | 1921 } |
1899 | 1922 |
1900 @override | 1923 @override |
1901 void beginUnnamedFunction(Token token) { | 1924 void beginUnnamedFunction(Token token) { |
1902 debugEvent("beginUnnamedFunction"); | 1925 debugEvent("beginUnnamedFunction"); |
1903 enterFunction(); | 1926 enterFunction(false); |
1904 } | 1927 } |
1905 | 1928 |
1906 @override | 1929 @override |
1907 void endFunction(Token getOrSet, Token endToken) { | 1930 void endFunction(Token getOrSet, Token endToken) { |
1908 debugEvent("Function"); | 1931 debugEvent("Function"); |
1909 Statement body = popStatement(); | 1932 Statement body = popStatement(); |
1910 AsyncMarker asyncModifier = pop(); | 1933 AsyncMarker asyncModifier = pop(); |
1911 if (functionNestingLevel != 0) { | 1934 if (functionNestingLevel != 0) { |
1912 exitLocalScope(); | 1935 exitLocalScope(); |
1913 } | 1936 } |
(...skipping 25 matching lines...) Expand all Loading... |
1939 Statement body = popStatement(); | 1962 Statement body = popStatement(); |
1940 AsyncMarker asyncModifier = pop(); | 1963 AsyncMarker asyncModifier = pop(); |
1941 exitLocalScope(); | 1964 exitLocalScope(); |
1942 FormalParameters formals = pop(); | 1965 FormalParameters formals = pop(); |
1943 exitFunction(); | 1966 exitFunction(); |
1944 List<TypeParameter> typeParameters = pop(); | 1967 List<TypeParameter> typeParameters = pop(); |
1945 FunctionNode function = formals.addToFunction(new FunctionNode(body, | 1968 FunctionNode function = formals.addToFunction(new FunctionNode(body, |
1946 typeParameters: typeParameters, asyncMarker: asyncModifier) | 1969 typeParameters: typeParameters, asyncMarker: asyncModifier) |
1947 ..fileOffset = beginToken.charOffset | 1970 ..fileOffset = beginToken.charOffset |
1948 ..fileEndOffset = token.charOffset); | 1971 ..fileEndOffset = token.charOffset); |
1949 push(new FunctionExpression(function)..fileOffset = beginToken.charOffset); | 1972 push(new shadow.FunctionExpression(function) |
| 1973 ..fileOffset = beginToken.charOffset); |
1950 } | 1974 } |
1951 | 1975 |
1952 @override | 1976 @override |
1953 void endDoWhileStatement( | 1977 void endDoWhileStatement( |
1954 Token doKeyword, Token whileKeyword, Token endToken) { | 1978 Token doKeyword, Token whileKeyword, Token endToken) { |
1955 debugEvent("DoWhileStatement"); | 1979 debugEvent("DoWhileStatement"); |
1956 Expression condition = popForValue(); | 1980 Expression condition = popForValue(); |
1957 Statement body = popStatement(); | 1981 Statement body = popStatement(); |
1958 JumpTarget continueTarget = exitContinueTarget(); | 1982 JumpTarget continueTarget = exitContinueTarget(); |
1959 JumpTarget breakTarget = exitBreakTarget(); | 1983 JumpTarget breakTarget = exitBreakTarget(); |
(...skipping 870 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2830 new KernelVariableBuilder(parameter, builder, builder.fileUri); | 2854 new KernelVariableBuilder(parameter, builder, builder.fileUri); |
2831 } | 2855 } |
2832 if (optional != null) { | 2856 if (optional != null) { |
2833 for (VariableDeclaration parameter in optional.formals) { | 2857 for (VariableDeclaration parameter in optional.formals) { |
2834 local[parameter.name] = | 2858 local[parameter.name] = |
2835 new KernelVariableBuilder(parameter, builder, builder.fileUri); | 2859 new KernelVariableBuilder(parameter, builder, builder.fileUri); |
2836 } | 2860 } |
2837 } | 2861 } |
2838 return new Scope(local, parent, isModifiable: false); | 2862 return new Scope(local, parent, isModifiable: false); |
2839 } | 2863 } |
| 2864 |
| 2865 void recordTypeInferenceTo(OldFunctionContext functionContext) { |
| 2866 if (functionContext == null) return; |
| 2867 int requiredParameterCount = required.length; |
| 2868 var positionalFormals = <shadow.VariableDeclaration>[]; |
| 2869 var namedFormals = const <shadow.VariableDeclaration>[]; |
| 2870 for (VariableDeclaration parameter in required) { |
| 2871 positionalFormals.add(parameter); |
| 2872 } |
| 2873 if (optional != null) { |
| 2874 throw new UnimplementedError(); |
| 2875 } |
| 2876 functionContext.recordFormals( |
| 2877 requiredParameterCount, positionalFormals, namedFormals); |
| 2878 } |
2840 } | 2879 } |
2841 | 2880 |
2842 /// Returns a block like this: | 2881 /// Returns a block like this: |
2843 /// | 2882 /// |
2844 /// { | 2883 /// { |
2845 /// statement; | 2884 /// statement; |
2846 /// body; | 2885 /// body; |
2847 /// } | 2886 /// } |
2848 /// | 2887 /// |
2849 /// If [body] is a [Block], it's returned with [statement] prepended to it. | 2888 /// If [body] is a [Block], it's returned with [statement] prepended to it. |
(...skipping 22 matching lines...) Expand all Loading... |
2872 } else if (node is PrefixBuilder) { | 2911 } else if (node is PrefixBuilder) { |
2873 return node.name; | 2912 return node.name; |
2874 } else if (node is ThisAccessor) { | 2913 } else if (node is ThisAccessor) { |
2875 return node.isSuper ? "super" : "this"; | 2914 return node.isSuper ? "super" : "this"; |
2876 } else if (node is BuilderAccessor) { | 2915 } else if (node is BuilderAccessor) { |
2877 return node.plainNameForRead; | 2916 return node.plainNameForRead; |
2878 } else { | 2917 } else { |
2879 return internalError("Unhandled: ${node.runtimeType}"); | 2918 return internalError("Unhandled: ${node.runtimeType}"); |
2880 } | 2919 } |
2881 } | 2920 } |
OLD | NEW |