Index: lib/src/codegen/side_effect_analysis.dart |
diff --git a/lib/src/codegen/side_effect_analysis.dart b/lib/src/codegen/side_effect_analysis.dart |
deleted file mode 100644 |
index da5de6bf00f5b91042c56c08585d5932e8a44584..0000000000000000000000000000000000000000 |
--- a/lib/src/codegen/side_effect_analysis.dart |
+++ /dev/null |
@@ -1,138 +0,0 @@ |
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-import 'package:analyzer/dart/ast/ast.dart'; |
-import 'package:analyzer/dart/ast/visitor.dart'; |
-import 'package:analyzer/dart/element/element.dart'; |
-import 'package:analyzer/src/generated/constant.dart'; |
-import 'package:analyzer/src/generated/error.dart' |
- show AnalysisErrorListener, ErrorReporter; |
-import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; |
-import 'package:analyzer/src/generated/source.dart' show Source; |
-import 'package:analyzer/src/dart/ast/ast.dart'; |
- |
-/// True is the expression can be evaluated multiple times without causing |
-/// code execution. This is true for final fields. This can be true for local |
-/// variables, if: |
-/// * they are not assigned within the [context]. |
-/// * they are not assigned in a function closure anywhere. |
-/// True is the expression can be evaluated multiple times without causing |
-/// code execution. This is true for final fields. This can be true for local |
-/// variables, if: |
-/// |
-/// * they are not assigned within the [context] scope. |
-/// * they are not assigned in a function closure anywhere. |
-/// |
-/// This method is used to avoid creating temporaries in cases where we know |
-/// we can safely re-evaluate [node] multiple times in [context]. This lets |
-/// us generate prettier code. |
-/// |
-/// This method is conservative: it should never return `true` unless it is |
-/// certain the [node] is stateless, because generated code may rely on the |
-/// correctness of a `true` value. However it may return `false` for things |
-/// that are in fact, stateless. |
-bool isStateless(FunctionBody function, Expression node, [AstNode context]) { |
- // `this` and `super` cannot be reassigned. |
- if (node is ThisExpression || node is SuperExpression) return true; |
- if (node is Identifier) { |
- var e = node.staticElement; |
- if (e is PropertyAccessorElement) { |
- e = e.variable; |
- } |
- if (e is VariableElement && !e.isSynthetic) { |
- if (e.isFinal) return true; |
- if (e is LocalVariableElement || e is ParameterElement) { |
- // make sure the local isn't mutated in the context. |
- return !_isPotentiallyMutated(function, e, context); |
- } |
- } |
- } |
- return false; |
-} |
- |
-/// Returns true if the local variable is potentially mutated within [context]. |
-/// This accounts for closures that may have been created outside of [context]. |
-bool _isPotentiallyMutated(FunctionBody function, VariableElement e, |
- [AstNode context]) { |
- if (function is FunctionBodyImpl && function.localVariableInfo == null) { |
- // TODO(jmesserly): this is a caching bug in Analyzer. They don't restore |
- // this info in some cases. |
- return true; |
- } |
- |
- if (function.isPotentiallyMutatedInClosure(e)) return true; |
- if (function.isPotentiallyMutatedInScope(e)) { |
- // Need to visit the context looking for assignment to this local. |
- if (context != null) { |
- var visitor = new _AssignmentFinder(e); |
- context.accept(visitor); |
- return visitor._potentiallyMutated; |
- } |
- return true; |
- } |
- return false; |
-} |
- |
-/// Adapted from VariableResolverVisitor. Finds an assignment to a given |
-/// local variable. |
-class _AssignmentFinder extends RecursiveAstVisitor { |
- final VariableElement _variable; |
- bool _potentiallyMutated = false; |
- |
- _AssignmentFinder(this._variable); |
- |
- @override |
- visitSimpleIdentifier(SimpleIdentifier node) { |
- // Ignore if qualified. |
- AstNode parent = node.parent; |
- if (parent is PrefixedIdentifier && identical(parent.identifier, node)) { |
- return; |
- } |
- if (parent is PropertyAccess && identical(parent.propertyName, node)) { |
- return; |
- } |
- if (parent is MethodInvocation && identical(parent.methodName, node)) { |
- return; |
- } |
- if (parent is ConstructorName) return; |
- if (parent is Label) return; |
- |
- if (node.inSetterContext() && node.staticElement == _variable) { |
- _potentiallyMutated = true; |
- } |
- } |
-} |
- |
-class ConstFieldVisitor { |
- final ConstantVisitor _constantVisitor; |
- |
- ConstFieldVisitor(TypeProvider types, Source source) |
- // TODO(jmesserly): support -D variables on the command line |
- : _constantVisitor = new ConstantVisitor( |
- new ConstantEvaluationEngine(types, new DeclaredVariables()), |
- new ErrorReporter(AnalysisErrorListener.NULL_LISTENER, source)); |
- |
- // TODO(jmesserly): this is used to determine if the field initialization is |
- // side effect free. We should make the check more general, as things like |
- // list/map literals/regexp are also side effect free and fairly common |
- // to use as field initializers. |
- bool isFieldInitConstant(VariableDeclaration field) => |
- field.initializer == null || computeConstant(field) != null; |
- |
- DartObject computeConstant(VariableDeclaration field) { |
- // If the constant is already computed by ConstantEvaluator, just return it. |
- VariableElement element = field.element; |
- var result = element.constantValue; |
- if (result != null) return result; |
- |
- // ConstantEvaluator will not compute constants for non-const fields, |
- // so run ConstantVisitor for those to figure out if the initializer is |
- // actually a constant (and therefore side effect free to evaluate). |
- assert(!field.isConst); |
- |
- var initializer = field.initializer; |
- if (initializer == null) return null; |
- return initializer.accept(_constantVisitor); |
- } |
-} |