OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library dart2js.ir_nodes_sexpr; | |
6 | |
7 import '../util/util.dart'; | |
8 import 'cps_ir_nodes.dart'; | |
9 | |
10 /// Generate a Lisp-like S-expression representation of an IR node as a string. | |
11 class SExpressionStringifier extends Visitor<String> with Indentation { | |
12 final Map<Definition, String> names = <Definition, String>{}; | |
13 | |
14 int _valueCounter = 0; | |
15 int _continuationCounter = 0; | |
16 | |
17 String newValueName() => 'v${_valueCounter++}'; | |
18 String newContinuationName() => 'k${_continuationCounter++}'; | |
19 | |
20 String visitFunctionDefinition(FunctionDefinition node) { | |
21 String name = node.element.name; | |
22 names[node.returnContinuation] = 'return'; | |
23 String parameters = node.parameters | |
24 .map((Parameter p) { | |
25 String name = p.hint.name; | |
26 names[p] = name; | |
27 return name; | |
28 }) | |
29 .join(' '); | |
30 String body = indentBlock(() => visit(node.body)); | |
31 return '$indentation(FunctionDefinition $name ($parameters return)\n' | |
32 '$body)'; | |
33 } | |
34 | |
35 String visitLetPrim(LetPrim node) { | |
36 String name = newValueName(); | |
37 names[node.primitive] = name; | |
38 String value = visit(node.primitive); | |
39 String body = visit(node.body); | |
40 return '$indentation(LetPrim $name $value)\n$body'; | |
41 } | |
42 | |
43 String visitLetCont(LetCont node) { | |
44 String cont = newContinuationName(); | |
45 names[node.continuation] = cont; | |
46 String parameters = node.continuation.parameters | |
47 .map((Parameter p) { | |
48 String name = newValueName(); | |
49 names[p] = name; | |
50 return ' $name'; | |
51 }) | |
52 .join(''); | |
53 String contBody = indentBlock(() => visit(node.continuation.body)); | |
54 String body = visit(node.body); | |
55 String op = node.continuation.isRecursive ? 'LetCont*' : 'LetCont'; | |
56 return '$indentation($op ($cont$parameters)\n' | |
57 '$contBody)\n' | |
58 '$body'; | |
59 } | |
60 | |
61 String formatArguments(Invoke node) { | |
62 int positionalArgumentCount = node.selector.positionalArgumentCount; | |
63 List<String> args = new List<String>(); | |
64 args.addAll(node.arguments.getRange(0, positionalArgumentCount) | |
65 .map((v) => names[v.definition])); | |
66 for (int i = 0; i < node.selector.namedArgumentCount; ++i) { | |
67 String name = node.selector.namedArguments[i]; | |
68 Definition arg = node.arguments[positionalArgumentCount + i].definition; | |
69 args.add("($name: $arg)"); | |
70 } | |
71 return args.join(' '); | |
72 } | |
73 | |
74 String visitInvokeStatic(InvokeStatic node) { | |
75 String name = node.target.name; | |
76 String cont = names[node.continuation.definition]; | |
77 String args = formatArguments(node); | |
78 return '$indentation(InvokeStatic $name $args $cont)'; | |
79 } | |
80 | |
81 String visitInvokeMethod(InvokeMethod node) { | |
82 String name = node.selector.name; | |
83 String rcv = names[node.receiver.definition]; | |
84 String cont = names[node.continuation.definition]; | |
85 String args = formatArguments(node); | |
86 return '$indentation(InvokeMethod $rcv $name $args $cont)'; | |
87 } | |
88 | |
89 String visitInvokeSuperMethod(InvokeSuperMethod node) { | |
90 String name = node.selector.name; | |
91 String cont = names[node.continuation.definition]; | |
92 String args = formatArguments(node); | |
93 return '$indentation(InvokeSuperMethod $name $args $cont)'; | |
94 } | |
95 | |
96 String visitInvokeConstructor(InvokeConstructor node) { | |
97 String callName; | |
98 if (node.target.name.isEmpty) { | |
99 callName = '${node.type}'; | |
100 } else { | |
101 callName = '${node.type}.${node.target.name}'; | |
102 } | |
103 String cont = names[node.continuation.definition]; | |
104 String args = formatArguments(node); | |
105 return '$indentation(InvokeConstructor $callName $args $cont)'; | |
106 } | |
107 | |
108 String visitConcatenateStrings(ConcatenateStrings node) { | |
109 String cont = names[node.continuation.definition]; | |
110 String args = node.arguments.map((v) => names[v.definition]).join(' '); | |
111 return '$indentation(ConcatenateStrings $args $cont)'; | |
112 } | |
113 | |
114 String visitInvokeContinuation(InvokeContinuation node) { | |
115 String cont = names[node.continuation.definition]; | |
116 String args = node.arguments.map((v) => names[v.definition]).join(' '); | |
117 String op = | |
118 node.isRecursive ? 'InvokeContinuation*' : 'InvokeContinuation'; | |
119 return '$indentation($op $cont $args)'; | |
120 } | |
121 | |
122 String visitBranch(Branch node) { | |
123 String condition = visit(node.condition); | |
124 String trueCont = names[node.trueContinuation.definition]; | |
125 String falseCont = names[node.falseContinuation.definition]; | |
126 return '$indentation(Branch $condition $trueCont $falseCont)'; | |
127 } | |
128 | |
129 String visitConstant(Constant node) { | |
130 return '(Constant ${node.expression.value.toStructuredString()})'; | |
131 } | |
132 | |
133 String visitThis(This node) { | |
134 return '(This)'; | |
135 } | |
136 | |
137 String visitReifyTypeVar(ReifyTypeVar node) { | |
138 return '$indentation(ReifyTypeVar ${node.typeVariable.name})'; | |
139 } | |
140 | |
141 String visitCreateFunction(CreateFunction node) { | |
142 String function = indentBlock(() => visit(node.definition)); | |
143 return '(CreateFunction\n$function)'; | |
144 } | |
145 | |
146 String visitParameter(Parameter node) { | |
147 // Parameters are visited directly in visitLetCont. | |
148 return '(Unexpected Parameter)'; | |
149 } | |
150 | |
151 String visitContinuation(Continuation node) { | |
152 // Continuations are visited directly in visitLetCont. | |
153 return '(Unexpected Continuation)'; | |
154 } | |
155 | |
156 String visitGetClosureVariable(GetClosureVariable node) { | |
157 return '(GetClosureVariable ${node.variable.name})'; | |
158 } | |
159 | |
160 String visitSetClosureVariable(SetClosureVariable node) { | |
161 String value = names[node.value.definition]; | |
162 String body = indentBlock(() => visit(node.body)); | |
163 return '$indentation(SetClosureVariable ${node.variable.name} $value\n' | |
164 '$body)'; | |
165 } | |
166 | |
167 String visitTypeOperator(TypeOperator node) { | |
168 String receiver = names[node.receiver.definition]; | |
169 String cont = names[node.continuation.definition]; | |
170 String operator = node.isTypeTest ? 'is' : 'as'; | |
171 return '$indentation(TypeOperator $operator $receiver ${node.type} $cont)'; | |
172 } | |
173 | |
174 String visitLiteralList(LiteralList node) { | |
175 String values = node.values.map((v) => names[v.definition]).join(' '); | |
176 return '(LiteralList ($values))'; | |
177 } | |
178 | |
179 String visitLiteralMap(LiteralMap node) { | |
180 String keys = node.entries.map((e) => names[e.key.definition]).join(' '); | |
181 String values = | |
182 node.entries.map((e) => names[e.value.definition]).join(' '); | |
183 return '(LiteralMap ($keys) ($values))'; | |
184 } | |
185 | |
186 String visitDeclareFunction(DeclareFunction node) { | |
187 String function = indentBlock(() => visit(node.definition)); | |
188 String body = indentBlock(() => visit(node.body)); | |
189 return '$indentation(DeclareFunction ${node.variable.name} =\n' | |
190 '$function in\n' | |
191 '$body)'; | |
192 } | |
193 | |
194 String visitIsTrue(IsTrue node) { | |
195 String value = names[node.value.definition]; | |
196 return '(IsTrue $value)'; | |
197 } | |
198 } | |
OLD | NEW |