Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Unified Diff: pkg/kernel/lib/type_propagation/visualizer.dart

Issue 2780513004: [Kernel] Remove code from the old type propagation. (Closed)
Patch Set: Remove empty status file section Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/kernel/lib/type_propagation/type_propagation.dart ('k') | pkg/kernel/lib/visitor.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/kernel/lib/type_propagation/visualizer.dart
diff --git a/pkg/kernel/lib/type_propagation/visualizer.dart b/pkg/kernel/lib/type_propagation/visualizer.dart
deleted file mode 100644
index 8cfd86a5ca42b48151eb0db084bb3a3c9adffdc1..0000000000000000000000000000000000000000
--- a/pkg/kernel/lib/type_propagation/visualizer.dart
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright (c) 2016, 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.
-library kernel.type_propagation.visualizer;
-
-import 'constraints.dart';
-import 'builder.dart';
-import 'solver.dart';
-import '../ast.dart';
-import '../text/ast_to_text.dart';
-import '../class_hierarchy.dart';
-
-/// Visualizes the constraint system using a Graphviz dot graph.
-///
-/// Variables are visualized as nodes and constraints as labeled edges.
-class Visualizer {
- final Program program;
- final Map<int, GraphNode> variableNodes = <int, GraphNode>{};
- final Map<int, FunctionNode> value2function = <int, FunctionNode>{};
- final Map<FunctionNode, int> function2value = <FunctionNode, int>{};
- final Map<int, Annotation> latticePointAnnotation = <int, Annotation>{};
- final Map<int, Annotation> valueAnnotation = <int, Annotation>{};
- FieldNames fieldNames;
- ConstraintSystem constraints;
- Solver solver;
- Builder builder;
-
- ClassHierarchy get hierarchy => builder.hierarchy;
-
- final Map<Member, Set<GraphNode>> _graphNodesInMember =
- <Member, Set<GraphNode>>{};
-
- Visualizer(this.program);
-
- static Set<GraphNode> _makeGraphNodeSet() => new Set<GraphNode>();
-
- Annotator getTextAnnotator() {
- return new TextAnnotator(this);
- }
-
- GraphNode getVariableNode(int variable) {
- return variableNodes[variable] ??= new GraphNode(variable);
- }
-
- /// Called from the builder to associate information with a variable.
- ///
- /// The [node] has two purposes: it ensures that the variable will show
- /// up in the graph for a the enclosing member, and the textual form of the
- /// node will be part of its label.
- ///
- /// The optional [info] argument provides additional context beyond the AST
- /// node. When a constraint variable has no logical 1:1 corresondence with
- /// an AST node, it is best to pick a nearby AST node and set the [info] to
- /// clarify its relationship with the node.
- void annotateVariable(int variable, TreeNode astNode, [String info]) {
- if (astNode != null || info != null) {
- if (astNode is VariableSet ||
- astNode is PropertySet ||
- astNode is StaticSet) {
- // These will also be registered for the right-hand side, which makes
- // for a better annotation.
- return;
- }
- var node = getVariableNode(variable);
- Member member = _getEnclosingMember(astNode);
- node.addAnnotation(member, astNode, info);
- _graphNodesInMember.putIfAbsent(member, _makeGraphNodeSet).add(node);
- }
- }
-
- void annotateAssign(int source, int destination, TreeNode node) {
- addEdge(source, destination, _getEnclosingMember(node), '');
- }
-
- void annotateSink(int source, int destination, TreeNode node) {
- addEdge(source, destination, _getEnclosingMember(node), 'sink');
- }
-
- void annotateLoad(int object, int field, int destination, Member member) {
- String fieldName = fieldNames.getDiagnosticNameOfField(field);
- addEdge(object, destination, member, 'Load[$fieldName]');
- }
-
- void annotateStore(int object, int field, int source, Member member) {
- String fieldName = fieldNames.getDiagnosticNameOfField(field);
- addEdge(source, object, member, 'Store[$fieldName]');
- }
-
- void annotateDirectStore(int object, int field, int source, Member member) {
- String fieldName = fieldNames.getDiagnosticNameOfField(field);
- addEdge(source, object, member, 'Store![$fieldName]');
- }
-
- void annotateLatticePoint(int point, TreeNode node, [String info]) {
- latticePointAnnotation[point] = new Annotation(node, info);
- }
-
- void annotateValue(int value, TreeNode node, [String info]) {
- valueAnnotation[value] = new Annotation(node, info);
- }
-
- String getLatticePointName(int latticePoint) {
- if (latticePoint < 0) return 'bottom';
- return latticePointAnnotation[latticePoint].toLabel();
- }
-
- String getValueName(int value) {
- return valueAnnotation[value].toLabel();
- }
-
- static Member _getEnclosingMember(TreeNode node) {
- while (node != null) {
- if (node is Member) return node;
- node = node.parent;
- }
- return null;
- }
-
- void addEdge(int source, int destination, Member member, String label) {
- var sourceNode = getVariableNode(source);
- var destinationNode = getVariableNode(destination);
- _graphNodesInMember.putIfAbsent(member, _makeGraphNodeSet)
- ..add(sourceNode)
- ..add(destinationNode);
- sourceNode.addEdgeTo(destinationNode, member, label);
- }
-
- void annotateFunction(int value, FunctionNode function) {
- value2function[value] = function;
- function2value[function] = value;
- }
-
- FunctionNode getFunctionFromValue(int value) {
- return value2function[value];
- }
-
- int getFunctionValue(FunctionNode node) {
- return function2value[node];
- }
-
- Set<GraphNode> _getNodesInMember(Member member) {
- return _graphNodesInMember.putIfAbsent(member, _makeGraphNodeSet);
- }
-
- String _getCodeAsLabel(Member member) {
- String code = debugNodeToString(member);
- code = escapeLabel(code);
- // Replace line-breaks with left-aligned breaks.
- code = code.replaceAll('\n', '\\l');
- return code;
- }
-
- String _getValueLabel(GraphNode node) {
- int latticePoint = solver.getVariableValue(node.variable);
- if (latticePoint < 0) return 'bottom';
- return escapeLabel(shorten(getLatticePointName(latticePoint)));
- }
-
- /// Returns the Graphviz Dot code a the subgraph relevant for [member].
- String dumpMember(Member member) {
- int freshIdCounter = 0;
- StringBuffer buffer = new StringBuffer();
- buffer.writeln('digraph {');
- String source = _getCodeAsLabel(member);
- buffer.writeln('source [shape=box,label="$source"]');
- for (GraphNode node in _getNodesInMember(member)) {
- int id = node.variable;
- String label = node.getAnnotationInContextOf(member);
- // Global nodes have a ton of edges that are visualized specially.
- // If the global node has a local annotation, also print its annotated
- // version somewhere, but omit all its edges.
- if (node.isGlobal) {
- if (label != '') {
- label += '\n${node.globalAnnotation.toLabel()}';
- buffer.writeln('$id [shape=record,label="$label"]');
- }
- continue;
- }
- String value = _getValueLabel(node);
- buffer.writeln('$id [shape=record,label="{$label|$value}"]');
- // Add outgoing edges.
- // Keep track of all that edges leave the context of the current member
- // ("external edges"). There can be a huge number of these, so we compact
- // them into a single outgoing edge so as not to flood the graph.
- Set<String> outgoingExternalEdgeLabels = new Set<String>();
- for (Edge edge in node.outputs) {
- if (edge.to.isLocal(member)) {
- buffer.writeln('$id -> ${edge.to.variable} [label="${edge.label}"]');
- } else if (outgoingExternalEdgeLabels.length < 3) {
- String annotation = edge.to.externalLabel;
- if (annotation != '') {
- if (edge.label != '') {
- annotation = '${edge.label} → $annotation';
- }
- outgoingExternalEdgeLabels.add(annotation);
- }
- } else if (outgoingExternalEdgeLabels.length == 3) {
- outgoingExternalEdgeLabels.add('...');
- }
- }
- // Emit the outgoing external edge.
- if (outgoingExternalEdgeLabels.isNotEmpty) {
- int freshId = ++freshIdCounter;
- String outLabel = outgoingExternalEdgeLabels.join('\n');
- buffer.writeln('x$freshId [shape=box,style=dotted,label="$outLabel"]');
- buffer.writeln('$id -> x$freshId [style=dotted]');
- }
- // Show ingoing external edges. As before, avoid flooding the graph in
- // case there are too many of them.
- Set<String> ingoingExternalEdgeLabels = new Set<String>();
- for (Edge edge in node.inputs) {
- GraphNode source = edge.from;
- if (source.isLocal(member)) continue;
- String annotation = source.externalLabel;
- if (annotation != '') {
- if (ingoingExternalEdgeLabels.length < 3) {
- if (edge.label != '') {
- annotation = '$annotation → ${edge.label}';
- }
- ingoingExternalEdgeLabels.add(annotation);
- } else {
- ingoingExternalEdgeLabels.add('...');
- break;
- }
- }
- }
- // Emit the ingoing external edge.
- if (ingoingExternalEdgeLabels.isNotEmpty) {
- int freshId = ++freshIdCounter;
- String sourceLabel = ingoingExternalEdgeLabels.join('\n');
- buffer.writeln('x$freshId '
- '[shape=box,style=dotted,label="$sourceLabel"]');
- buffer.writeln('x$freshId -> ${node.variable} [style=dotted]');
- }
- }
- buffer.writeln('}');
- return '$buffer';
- }
-}
-
-class Annotation {
- final TreeNode node;
- final String info;
-
- Annotation(this.node, this.info);
-
- String toLabel() {
- if (node == null && info == null) return '(missing annotation)';
- if (node == null) return escapeLabel(info);
- String label = node is NullLiteral
- ? 'null literal'
- : node is FunctionNode ? shorten('${node.parent}') : shorten('$node');
- if (info != null) {
- label = '$info: $label';
- }
- label = escapeLabel(label);
- return label;
- }
-
- String toLabelWithContext(Member member) {
- String label = toLabel();
- if (node == member) {
- return label;
- } else {
- return '$label in $member';
- }
- }
-}
-
-class GraphNode {
- final int variable;
- final List<Edge> inputs = <Edge>[];
- final List<Edge> outputs = <Edge>[];
- final List<Annotation> annotations = <Annotation>[];
-
- /// The annotation to show when visualized in the context of a given member.
- final Map<Member, Annotation> annotationForContext = <Member, Annotation>{};
-
- GraphNode(this.variable);
-
- bool get isGlobal => annotationForContext.containsKey(null);
- Annotation get globalAnnotation => annotationForContext[null];
- bool isInScope(Member member) => annotationForContext.containsKey(member);
- bool isLocal(Member member) => !isGlobal && isInScope(member);
-
- /// The label to show for the given node when seen from the context of
- /// another member.
- String get externalLabel {
- if (isGlobal) return globalAnnotation.toLabel();
- if (annotationForContext.isEmpty) return '$variable';
- Member member = annotationForContext.keys.first;
- Annotation annotation = annotationForContext[member];
- return '$variable:' + annotation.toLabelWithContext(member);
- }
-
- String getAnnotationInContextOf(Member member) {
- if (annotationForContext.isEmpty) return '';
- Annotation annotation = annotationForContext[member];
- if (annotation != null) return '$variable:' + annotation.toLabel();
- annotation =
- annotationForContext[null] ?? annotationForContext.values.first;
- return '$variable:' + annotation.toLabelWithContext(member);
- }
-
- void addEdgeTo(GraphNode other, Member member, String label) {
- Edge edge = new Edge(this, other, member, label);
- outputs.add(edge);
- other.inputs.add(edge);
- }
-
- void addAnnotation(Member member, TreeNode astNode, String info) {
- var annotation = new Annotation(astNode, info);
- annotations.add(annotation);
- annotationForContext[member] = annotation;
- }
-}
-
-class Edge {
- final GraphNode from, to;
- final Member member;
- final String label;
-
- Edge(this.from, this.to, this.member, this.label);
-}
-
-final RegExp escapeRegexp = new RegExp('["{}<>|]', multiLine: true);
-
-/// Escapes characters in [text] so it can be used as part of a label.
-String escapeLabel(String text) {
- return text.replaceAllMapped(escapeRegexp, (m) => '\\${m.group(0)}');
-}
-
-String shorten(String text) {
- text = text.replaceAll('\n ', ' ').replaceAll('\n', ' ').trim();
- if (text.length > 60) {
- return text.substring(0, 30) + '...' + text.substring(text.length - 27);
- }
- return text;
-}
-
-class TextAnnotator extends Annotator {
- final Visualizer visualizer;
- final Map<VariableDeclaration, int> variables = <VariableDeclaration, int>{};
- final Map<FunctionNode, int> functionReturns = <FunctionNode, int>{};
-
- Builder get builder => visualizer.builder;
-
- String getReference(Node node, Printer printer) {
- if (node is Class) return printer.getClassReference(node);
- if (node is Member) return printer.getMemberReference(node);
- if (node is Library) return printer.getLibraryReference(node);
- return debugNodeToString(node);
- }
-
- String getValueForVariable(Printer printer, int variable) {
- if (variable == null) {
- return '<missing type>';
- }
- var value = visualizer.solver.getValueInferredForVariable(variable);
- return printer.getInferredValueString(value);
- }
-
- TextAnnotator(this.visualizer) {
- // The correspondence between AST and constraint system is exposed by the
- // builder, but only at the level of Members.
- // To get to the correspondence at the statement/expression level, we use
- // the annotation map from the visualizer API.
- // TODO(asgerf): If we use these annotations for testing, the necessary
- // bindings should arguably be part of the API for the Builder.
- visualizer.variableNodes.forEach((int variable, GraphNode node) {
- for (Annotation annotation in node.annotations) {
- if (annotation.node is VariableDeclaration && annotation.info == null) {
- variables[annotation.node] = variable;
- }
- if (annotation.node is FunctionNode && annotation.info == 'return') {
- functionReturns[annotation.node] = variable;
- }
- }
- });
- }
-
- String annotateVariable(Printer printer, VariableDeclaration node) {
- return getValueForVariable(
- printer, builder.global.parameters[node] ?? variables[node]);
- }
-
- String annotateReturn(Printer printer, FunctionNode node) {
- if (node.parent is Constructor) return null;
- return getValueForVariable(printer, builder.global.returns[node]);
- }
-
- String annotateField(Printer printer, Field node) {
- return getValueForVariable(printer, builder.global.fields[node]);
- }
-}
« no previous file with comments | « pkg/kernel/lib/type_propagation/type_propagation.dart ('k') | pkg/kernel/lib/visitor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698