| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 backend_ast_emitter; | 5 library backend_ast_emitter; |
| 6 | 6 |
| 7 import '../tree_ir/tree_ir_nodes.dart' as tree; | 7 import '../tree_ir/tree_ir_nodes.dart' as tree; |
| 8 import 'backend_ast_nodes.dart'; | 8 import 'backend_ast_nodes.dart'; |
| 9 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
| 10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
| 11 import '../dart_types.dart'; | 11 import '../dart_types.dart'; |
| 12 import '../elements/elements.dart'; | 12 import '../elements/elements.dart'; |
| 13 import '../elements/modelx.dart' as modelx; | 13 import '../elements/modelx.dart' as modelx; |
| 14 import '../universe/universe.dart'; | 14 import '../universe/universe.dart'; |
| 15 import '../tree/tree.dart' as tree show Modifiers; | 15 import '../tree/tree.dart' as tree show Modifiers; |
| 16 | 16 |
| 17 /// Translates the dart_tree IR to Dart backend AST. | 17 /// Translates the dart_tree IR to Dart backend AST. |
| 18 ExecutableDefinition emit(tree.ExecutableDefinition definition) { | 18 RootNode emit(tree.RootNode root) { |
| 19 return new ASTEmitter().emit(definition, new BuilderContext<Statement>()); | 19 return new ASTEmitter().emit(root); |
| 20 } | 20 } |
| 21 | 21 |
| 22 // TODO(johnniwinther): Split into function/block state. | 22 // TODO(johnniwinther): Split into function/block state. |
| 23 class BuilderContext<T> { | 23 class BuilderContext<T> { |
| 24 /// Builder context for the enclosing function, or null if the current | 24 /// Builder context for the enclosing function, or null if the current |
| 25 /// function is not a local function. | 25 /// function is not a local function. |
| 26 BuilderContext<T> _parent; | 26 BuilderContext<T> _parent; |
| 27 | 27 |
| 28 /// Variables to be hoisted at the top of the current function. | 28 /// Variables to be hoisted at the top of the current function. |
| 29 final List<VariableDeclaration> variables = <VariableDeclaration>[]; | 29 final List<VariableDeclaration> variables = <VariableDeclaration>[]; |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 | 196 |
| 197 /// Add [statement] to the current block. | 197 /// Add [statement] to the current block. |
| 198 void addStatement(T statement) { | 198 void addStatement(T statement) { |
| 199 _statementBuffer.add(statement); | 199 _statementBuffer.add(statement); |
| 200 } | 200 } |
| 201 | 201 |
| 202 /// The statements in the current block. | 202 /// The statements in the current block. |
| 203 Iterable<T> get statements => _statementBuffer; | 203 Iterable<T> get statements => _statementBuffer; |
| 204 } | 204 } |
| 205 | 205 |
| 206 | |
| 207 /// Translates the dart_tree IR to Dart backend AST. | 206 /// Translates the dart_tree IR to Dart backend AST. |
| 208 /// An instance of this class should only be used once; a fresh emitter | 207 /// An instance of this class should only be used once; a fresh emitter |
| 209 /// must be created for each function to be emitted. | 208 /// must be created for each function to be emitted. |
| 210 class ASTEmitter | 209 class ASTEmitter |
| 211 extends tree.Visitor1<dynamic, Expression, BuilderContext<Statement>> { | 210 extends tree.StatementVisitor1<dynamic, BuilderContext<Statement>> |
| 211 with tree.ExpressionVisitor1<Expression, BuilderContext<Statement>>, |
| 212 tree.RootVisitor1<RootNode, BuilderContext<Statement>>, |
| 213 tree.InitializerVisitor1<Initializer, BuilderContext<Statement>> { |
| 212 | 214 |
| 213 ExecutableDefinition emit(tree.ExecutableDefinition definition, | 215 RootNode emit(tree.RootNode node) { |
| 214 BuilderContext<Statement> context) { | 216 return visitRootNode(node, new BuilderContext<Statement>()); |
| 215 if (definition is tree.FieldDefinition) { | |
| 216 return emitField(definition, context); | |
| 217 } else if (definition is tree.ConstructorDefinition) { | |
| 218 return emitConstructor(definition, context); | |
| 219 } | |
| 220 assert(definition is tree.FunctionDefinition); | |
| 221 return emitFunction(definition, context); | |
| 222 } | 217 } |
| 223 | 218 |
| 224 FieldDefinition emitField(tree.FieldDefinition definition, | 219 @override |
| 225 BuilderContext<Statement> context) { | 220 FieldDefinition visitFieldDefinition(tree.FieldDefinition definition, |
| 221 BuilderContext<Statement> context) { |
| 226 context.currentElement = definition.element; | 222 context.currentElement = definition.element; |
| 227 Expression initializer; | 223 Expression initializer; |
| 228 if (definition.hasInitializer) { | 224 if (!definition.isEmpty) { |
| 229 visitStatement(definition.body, context); | 225 visitStatement(definition.body, context); |
| 230 List<Statement> bodyParts; | 226 List<Statement> bodyParts; |
| 231 for (tree.Variable variable in context.variableNames.keys) { | 227 for (tree.Variable variable in context.variableNames.keys) { |
| 232 if (!context.declaredVariables.contains(variable)) { | 228 if (!context.declaredVariables.contains(variable)) { |
| 233 context.addDeclaration(variable); | 229 context.addDeclaration(variable); |
| 234 } | 230 } |
| 235 } | 231 } |
| 236 if (context.variables.length > 0) { | 232 if (context.variables.length > 0) { |
| 237 bodyParts = new List<Statement>(); | 233 bodyParts = new List<Statement>(); |
| 238 bodyParts.add(new VariableDeclarations(context.variables)); | 234 bodyParts.add(new VariableDeclarations(context.variables)); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 266 bool _recognizeTrailingReturn(Statement statement) { | 262 bool _recognizeTrailingReturn(Statement statement) { |
| 267 if (statement is Return) { | 263 if (statement is Return) { |
| 268 Expression expr = statement.expression; | 264 Expression expr = statement.expression; |
| 269 if (expr == null || expr is Literal && expr.value.isNull) { | 265 if (expr == null || expr is Literal && expr.value.isNull) { |
| 270 return true; | 266 return true; |
| 271 } | 267 } |
| 272 } | 268 } |
| 273 return false; | 269 return false; |
| 274 } | 270 } |
| 275 | 271 |
| 276 FunctionExpression emitConstructor(tree.ConstructorDefinition definition, | 272 @override |
| 277 BuilderContext<Statement> context) { | 273 FunctionExpression visitConstructorDefinition( |
| 274 tree.ConstructorDefinition definition, |
| 275 BuilderContext<Statement> context) { |
| 278 context.currentElement = definition.element; | 276 context.currentElement = definition.element; |
| 279 | 277 |
| 280 Parameters parameters = emitRootParameters(definition, context); | 278 Parameters parameters = emitRootParameters( |
| 279 definition, definition.defaultParameterValues, context); |
| 281 | 280 |
| 282 // Declare parameters. | 281 // Declare parameters. |
| 283 for (tree.Variable param in definition.parameters) { | 282 for (tree.Variable param in definition.parameters) { |
| 284 context.variableNames[param] = param.element.name; | 283 context.variableNames[param] = param.element.name; |
| 285 context.usedVariableNames.add(param.element.name); | 284 context.usedVariableNames.add(param.element.name); |
| 286 context.declaredVariables.add(param); | 285 context.declaredVariables.add(param); |
| 287 } | 286 } |
| 288 | 287 |
| 289 List<Expression> initializers; | 288 List<Initializer> initializers; |
| 290 Statement body; | 289 Statement body; |
| 291 | 290 |
| 292 if (!definition.isAbstract) { | 291 if (!definition.isEmpty) { |
| 293 initializers = | 292 initializers = |
| 294 definition.initializers.map((tree.Initializer initializer) { | 293 definition.initializers.map((tree.Initializer initializer) { |
| 295 return visitExpression(initializer, context); | 294 return visitInitializer(initializer, context); |
| 296 }).toList(); | 295 }).toList(); |
| 297 | 296 |
| 298 context.firstStatement = definition.body; | 297 context.firstStatement = definition.body; |
| 299 visitStatement(definition.body, context); | 298 visitStatement(definition.body, context); |
| 300 context.removeTrailingReturn(_recognizeTrailingReturn); | 299 context.removeTrailingReturn(_recognizeTrailingReturn); |
| 301 | 300 |
| 302 // Some of the variable declarations have already been added | 301 // Some of the variable declarations have already been added |
| 303 // if their first assignment could be pulled into the initializer. | 302 // if their first assignment could be pulled into the initializer. |
| 304 // Add the remaining variable declarations now. | 303 // Add the remaining variable declarations now. |
| 305 for (tree.Variable variable in context.variableNames.keys) { | 304 for (tree.Variable variable in context.variableNames.keys) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 FunctionType functionType = context.currentElement.type; | 336 FunctionType functionType = context.currentElement.type; |
| 338 | 337 |
| 339 return new ConstructorDefinition( | 338 return new ConstructorDefinition( |
| 340 parameters, | 339 parameters, |
| 341 body, | 340 body, |
| 342 initializers, | 341 initializers, |
| 343 context.currentElement.name, definition.element.isConst) | 342 context.currentElement.name, definition.element.isConst) |
| 344 ..element = context.currentElement; | 343 ..element = context.currentElement; |
| 345 } | 344 } |
| 346 | 345 |
| 347 FunctionExpression emitFunction(tree.FunctionDefinition definition, | 346 @override |
| 348 BuilderContext<Statement> context) { | 347 FunctionExpression visitFunctionDefinition( |
| 348 tree.FunctionDefinition definition, |
| 349 BuilderContext<Statement> context) { |
| 349 context.currentElement = definition.element; | 350 context.currentElement = definition.element; |
| 350 | 351 |
| 351 Parameters parameters = emitRootParameters(definition, context); | 352 Parameters parameters = emitRootParameters( |
| 353 definition, definition.defaultParameterValues, context); |
| 352 | 354 |
| 353 // Declare parameters. | 355 // Declare parameters. |
| 354 for (tree.Variable param in definition.parameters) { | 356 for (tree.Variable param in definition.parameters) { |
| 355 context.variableNames[param] = param.element.name; | 357 context.variableNames[param] = param.element.name; |
| 356 context.usedVariableNames.add(param.element.name); | 358 context.usedVariableNames.add(param.element.name); |
| 357 context.declaredVariables.add(param); | 359 context.declaredVariables.add(param); |
| 358 } | 360 } |
| 359 | 361 |
| 360 Statement body; | 362 Statement body; |
| 361 if (definition.isAbstract) { | 363 if (definition.isEmpty) { |
| 362 body = new EmptyStatement(); | 364 body = new EmptyStatement(); |
| 363 } else { | 365 } else { |
| 364 context.firstStatement = definition.body; | 366 context.firstStatement = definition.body; |
| 365 visitStatement(definition.body, context); | 367 visitStatement(definition.body, context); |
| 366 context.removeTrailingReturn(_recognizeTrailingReturn); | 368 context.removeTrailingReturn(_recognizeTrailingReturn); |
| 367 | 369 |
| 368 // Some of the variable declarations have already been added | 370 // Some of the variable declarations have already been added |
| 369 // if their first assignment could be pulled into the initializer. | 371 // if their first assignment could be pulled into the initializer. |
| 370 // Add the remaining variable declarations now. | 372 // Add the remaining variable declarations now. |
| 371 for (tree.Variable variable in context.variableNames.keys) { | 373 for (tree.Variable variable in context.variableNames.keys) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 body, | 409 body, |
| 408 name: context.currentElement.name, | 410 name: context.currentElement.name, |
| 409 returnType: TypeGenerator.createOptionalType(functionType.returnType), | 411 returnType: TypeGenerator.createOptionalType(functionType.returnType), |
| 410 isGetter: context.currentElement.isGetter, | 412 isGetter: context.currentElement.isGetter, |
| 411 isSetter: context.currentElement.isSetter) | 413 isSetter: context.currentElement.isSetter) |
| 412 ..element = context.currentElement; | 414 ..element = context.currentElement; |
| 413 } | 415 } |
| 414 | 416 |
| 415 /// Emits parameters that are not nested inside other parameters. | 417 /// Emits parameters that are not nested inside other parameters. |
| 416 /// Root parameters can have default values, while inner parameters cannot. | 418 /// Root parameters can have default values, while inner parameters cannot. |
| 417 Parameters emitRootParameters(tree.FunctionDefinition function, | 419 Parameters emitRootParameters(tree.RootNode function, |
| 420 List<ConstantExpression> defaults, |
| 418 BuilderContext<Statement> context) { | 421 BuilderContext<Statement> context) { |
| 419 FunctionType functionType = function.element.type; | 422 FunctionType functionType = function.element.type; |
| 420 List<Parameter> required = TypeGenerator.createParameters( | 423 List<Parameter> required = TypeGenerator.createParameters( |
| 421 functionType.parameterTypes, | 424 functionType.parameterTypes, |
| 422 context: context, | 425 context: context, |
| 423 elements: function.parameters.map((p) => p.element)); | 426 elements: function.parameters.map((p) => p.element)); |
| 424 bool optionalParametersAreNamed = !functionType.namedParameters.isEmpty; | 427 bool optionalParametersAreNamed = !functionType.namedParameters.isEmpty; |
| 425 List<Parameter> optional = TypeGenerator.createParameters( | 428 List<Parameter> optional = TypeGenerator.createParameters( |
| 426 optionalParametersAreNamed | 429 optionalParametersAreNamed |
| 427 ? functionType.namedParameterTypes | 430 ? functionType.namedParameterTypes |
| 428 : functionType.optionalParameterTypes, | 431 : functionType.optionalParameterTypes, |
| 429 context: context, | 432 context: context, |
| 430 defaultValues: function.defaultParameterValues, | 433 defaultValues: defaults, |
| 431 elements: function.parameters.skip(required.length) | 434 elements: function.parameters.skip(required.length) |
| 432 .map((p) => p.element)); | 435 .map((p) => p.element)); |
| 433 return new Parameters(required, optional, optionalParametersAreNamed); | 436 return new Parameters(required, optional, optionalParametersAreNamed); |
| 434 } | 437 } |
| 435 | 438 |
| 436 /// True if the two expressions are a reference to the same variable. | 439 /// True if the two expressions are a reference to the same variable. |
| 437 bool isSameVariable(Receiver e1, Receiver e2) { | 440 bool isSameVariable(Receiver e1, Receiver e2) { |
| 438 return e1 is Identifier && | 441 return e1 is Identifier && |
| 439 e2 is Identifier && | 442 e2 is Identifier && |
| 440 e1.element is VariableElement && | 443 e1.element is VariableElement && |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 } | 873 } |
| 871 | 874 |
| 872 @override | 875 @override |
| 873 Expression visitVariableUse(tree.VariableUse exp, | 876 Expression visitVariableUse(tree.VariableUse exp, |
| 874 BuilderContext<Statement> context) { | 877 BuilderContext<Statement> context) { |
| 875 return context.makeVariableAccess(exp.variable); | 878 return context.makeVariableAccess(exp.variable); |
| 876 } | 879 } |
| 877 | 880 |
| 878 FunctionExpression makeSubFunction(tree.FunctionDefinition function, | 881 FunctionExpression makeSubFunction(tree.FunctionDefinition function, |
| 879 BuilderContext<Statement> context) { | 882 BuilderContext<Statement> context) { |
| 880 return emit(function, new BuilderContext<Statement>.inner(context)); | 883 return visitFunctionDefinition(function, |
| 884 new BuilderContext<Statement>.inner(context)); |
| 881 } | 885 } |
| 882 | 886 |
| 883 @override | 887 @override |
| 884 Expression visitFunctionExpression(tree.FunctionExpression exp, | 888 Expression visitFunctionExpression(tree.FunctionExpression exp, |
| 885 BuilderContext<Statement> context) { | 889 BuilderContext<Statement> context) { |
| 886 return makeSubFunction(exp.definition, context)..name = null; | 890 return makeSubFunction(exp.definition, context)..name = null; |
| 887 } | 891 } |
| 888 | 892 |
| 889 @override | 893 @override |
| 890 void visitFunctionDeclaration(tree.FunctionDeclaration node, | 894 void visitFunctionDeclaration(tree.FunctionDeclaration node, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 914 bodyParts = new List<Statement>(); | 918 bodyParts = new List<Statement>(); |
| 915 bodyParts.add(new VariableDeclarations(inner.variables)); | 919 bodyParts.add(new VariableDeclarations(inner.variables)); |
| 916 bodyParts.addAll(inner.statements); | 920 bodyParts.addAll(inner.statements); |
| 917 } else { | 921 } else { |
| 918 bodyParts = inner.statements; | 922 bodyParts = inner.statements; |
| 919 } | 923 } |
| 920 return bodyParts; | 924 return bodyParts; |
| 921 } | 925 } |
| 922 | 926 |
| 923 @override | 927 @override |
| 924 Expression visitFieldInitializer(tree.FieldInitializer node, | 928 Initializer visitFieldInitializer(tree.FieldInitializer node, |
| 925 BuilderContext<Statement> context) { | 929 BuilderContext<Statement> context) { |
| 926 return new FieldInitializer(node.element, | 930 return new FieldInitializer(node.element, |
| 927 ensureExpression(buildInInitializerContext(node.body, context))); | 931 ensureExpression(buildInInitializerContext(node.body, context))); |
| 928 } | 932 } |
| 929 | 933 |
| 930 @override | 934 @override |
| 931 Expression visitSuperInitializer(tree.SuperInitializer node, | 935 Initializer visitSuperInitializer(tree.SuperInitializer node, |
| 932 BuilderContext<Statement> context) { | 936 BuilderContext<Statement> context) { |
| 933 List<Argument> arguments = node.arguments.map((tree.Statement argument) { | 937 List<Argument> arguments = node.arguments.map((tree.Statement argument) { |
| 934 return ensureExpression(buildInInitializerContext(argument, context)); | 938 return ensureExpression(buildInInitializerContext(argument, context)); |
| 935 }).toList(); | 939 }).toList(); |
| 936 return new SuperInitializer(node.target, | 940 return new SuperInitializer(node.target, |
| 937 emitArguments(arguments, node.selector)); | 941 emitArguments(arguments, node.selector)); |
| 938 } | 942 } |
| 939 | 943 |
| 940 @override | 944 @override |
| 941 Expression visitTypeExpression(tree.TypeExpression node, arg) { | 945 Expression visitTypeExpression(tree.TypeExpression node, arg) { |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1251 | 1255 |
| 1252 /// Maps parameter names to their bindings. | 1256 /// Maps parameter names to their bindings. |
| 1253 Map<String, tree.Variable> environment = <String, tree.Variable>{}; | 1257 Map<String, tree.Variable> environment = <String, tree.Variable>{}; |
| 1254 | 1258 |
| 1255 /// Parameters that are currently shadowed by another parameter. | 1259 /// Parameters that are currently shadowed by another parameter. |
| 1256 Set<tree.Variable> shadowedParameters = new Set<tree.Variable>(); | 1260 Set<tree.Variable> shadowedParameters = new Set<tree.Variable>(); |
| 1257 | 1261 |
| 1258 /// Parameters that are used in a context where it is shadowed. | 1262 /// Parameters that are used in a context where it is shadowed. |
| 1259 Set<tree.Variable> hasShadowedUse = new Set<tree.Variable>(); | 1263 Set<tree.Variable> hasShadowedUse = new Set<tree.Variable>(); |
| 1260 | 1264 |
| 1261 void unshadow(tree.ExecutableDefinition definition) { | 1265 void unshadow(tree.RootNode definition) { |
| 1262 // Fields have no parameters. | 1266 if (definition.isEmpty) return; |
| 1263 if (definition is tree.FieldDefinition) return; | 1267 unshadowFunction(definition); |
| 1264 visitFunctionDefinition(definition); | |
| 1265 } | 1268 } |
| 1266 | 1269 |
| 1267 visitFunctionDefinition(tree.FunctionDefinition definition) { | 1270 void unshadowFunction(tree.RootNode definition) { |
| 1268 if (definition.isAbstract) return; | |
| 1269 var oldShadow = shadowedParameters; | 1271 var oldShadow = shadowedParameters; |
| 1270 var oldEnvironment = environment; | 1272 var oldEnvironment = environment; |
| 1271 environment = new Map<String, tree.Variable>.from(environment); | 1273 environment = new Map<String, tree.Variable>.from(environment); |
| 1272 shadowedParameters = new Set<tree.Variable>.from(shadowedParameters); | 1274 shadowedParameters = new Set<tree.Variable>.from(shadowedParameters); |
| 1273 for (tree.Variable param in definition.parameters) { | 1275 for (tree.Variable param in definition.parameters) { |
| 1274 tree.Variable oldVariable = environment[param.element.name]; | 1276 tree.Variable oldVariable = environment[param.element.name]; |
| 1275 if (oldVariable != null) { | 1277 if (oldVariable != null) { |
| 1276 shadowedParameters.add(oldVariable); | 1278 shadowedParameters.add(oldVariable); |
| 1277 } | 1279 } |
| 1278 environment[param.element.name] = param; | 1280 environment[param.element.name] = param; |
| 1279 } | 1281 } |
| 1280 visitStatement(definition.body); | 1282 definition.forEachBody(visitStatement); |
| 1281 environment = oldEnvironment; | 1283 environment = oldEnvironment; |
| 1282 shadowedParameters = oldShadow; | 1284 shadowedParameters = oldShadow; |
| 1283 | 1285 |
| 1284 for (int i=0; i<definition.parameters.length; i++) { | 1286 for (int i=0; i<definition.parameters.length; i++) { |
| 1285 tree.Variable param = definition.parameters[i]; | 1287 tree.Variable param = definition.parameters[i]; |
| 1286 if (hasShadowedUse.remove(param)) { | 1288 if (hasShadowedUse.remove(param)) { |
| 1287 tree.Variable newParam = new tree.Variable(definition.element, | 1289 tree.Variable newParam = new tree.Variable(definition.element, |
| 1288 param.element); | 1290 param.element); |
| 1289 definition.parameters[i] = newParam; | 1291 definition.parameters[i] = newParam; |
| 1290 definition.body = new tree.Assign(param, new tree.VariableUse(newParam), | 1292 definition.replaceEachBody((tree.Statement body) { |
| 1291 definition.body); | 1293 return new tree.Assign(param, new tree.VariableUse(newParam), body); |
| 1294 }); |
| 1292 newParam.writeCount = 1; // Being a parameter counts as a write. | 1295 newParam.writeCount = 1; // Being a parameter counts as a write. |
| 1293 param.writeCount--; // Not a parameter anymore. | 1296 param.writeCount--; // Not a parameter anymore. |
| 1294 } | 1297 } |
| 1295 } | 1298 } |
| 1296 } | 1299 } |
| 1297 | 1300 |
| 1298 @override | 1301 @override |
| 1302 void visitInnerFunction(tree.FunctionDefinition definition) { |
| 1303 unshadowFunction(definition); |
| 1304 } |
| 1305 |
| 1306 @override |
| 1299 visitVariable(tree.Variable variable) { | 1307 visitVariable(tree.Variable variable) { |
| 1300 if (shadowedParameters.contains(variable)) { | 1308 if (shadowedParameters.contains(variable)) { |
| 1301 hasShadowedUse.add(variable); | 1309 hasShadowedUse.add(variable); |
| 1302 } | 1310 } |
| 1303 } | 1311 } |
| 1304 | 1312 |
| 1305 } | 1313 } |
| 1306 | 1314 |
| 1307 // TODO(johnniwinther): Remove this when the dart `backend_ast` does not need | 1315 // TODO(johnniwinther): Remove this when the dart `backend_ast` does not need |
| 1308 // [Element] for entities. | 1316 // [Element] for entities. |
| 1309 class _SyntheticLocalVariableElement extends modelx.VariableElementX | 1317 class _SyntheticLocalVariableElement extends modelx.VariableElementX |
| 1310 implements LocalVariableElement { | 1318 implements LocalVariableElement { |
| 1311 | 1319 |
| 1312 _SyntheticLocalVariableElement(String name, | 1320 _SyntheticLocalVariableElement(String name, |
| 1313 ExecutableElement enclosingElement, | 1321 ExecutableElement enclosingElement, |
| 1314 modelx.VariableList variables) | 1322 modelx.VariableList variables) |
| 1315 : super(name, ElementKind.VARIABLE, enclosingElement, variables, null); | 1323 : super(name, ElementKind.VARIABLE, enclosingElement, variables, null); |
| 1316 | 1324 |
| 1317 ExecutableElement get executableContext => enclosingElement; | 1325 ExecutableElement get executableContext => enclosingElement; |
| 1318 | 1326 |
| 1319 ExecutableElement get memberContext => executableContext.memberContext; | 1327 ExecutableElement get memberContext => executableContext.memberContext; |
| 1320 | 1328 |
| 1321 bool get isLocal => true; | 1329 bool get isLocal => true; |
| 1322 | 1330 |
| 1323 LibraryElement get implementationLibrary => enclosingElement.library; | 1331 LibraryElement get implementationLibrary => enclosingElement.library; |
| 1324 } | 1332 } |
| OLD | NEW |