OLD | NEW |
| (Empty) |
1 // Copyright (c) 2017, 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 /// Algorithm to serialize expressions into the format used by summaries. | |
6 library summary.src.expression_serializer; | |
7 | |
8 import 'package:front_end/src/fasta/scanner/token_constants.dart'; | |
9 | |
10 import 'model.dart'; | |
11 | |
12 /// Translate a parser binary operation into an operation in the summary format. | |
13 UnlinkedExprOperation _binaryOpFor(int operatorKind) { | |
14 switch (operatorKind) { | |
15 case AMPERSAND_TOKEN: | |
16 return UnlinkedExprOperation.bitAnd; | |
17 case AMPERSAND_AMPERSAND_TOKEN: | |
18 return UnlinkedExprOperation.and; | |
19 case BANG_EQ_TOKEN: | |
20 return UnlinkedExprOperation.notEqual; | |
21 case BAR_TOKEN: | |
22 return UnlinkedExprOperation.bitOr; | |
23 case BAR_BAR_TOKEN: | |
24 return UnlinkedExprOperation.or; | |
25 case CARET_TOKEN: | |
26 return UnlinkedExprOperation.bitXor; | |
27 case EQ_EQ_TOKEN: | |
28 return UnlinkedExprOperation.equal; | |
29 case GT_TOKEN: | |
30 return UnlinkedExprOperation.greater; | |
31 case GT_EQ_TOKEN: | |
32 return UnlinkedExprOperation.greaterEqual; | |
33 case GT_GT_TOKEN: | |
34 return UnlinkedExprOperation.bitShiftRight; | |
35 case LT_TOKEN: | |
36 return UnlinkedExprOperation.less; | |
37 case LT_EQ_TOKEN: | |
38 return UnlinkedExprOperation.lessEqual; | |
39 case LT_LT_TOKEN: | |
40 return UnlinkedExprOperation.bitShiftLeft; | |
41 case MINUS_TOKEN: | |
42 return UnlinkedExprOperation.subtract; | |
43 case PERCENT_TOKEN: | |
44 return UnlinkedExprOperation.modulo; | |
45 case PERIOD_TOKEN: | |
46 return UnlinkedExprOperation.extractProperty; | |
47 case PLUS_TOKEN: | |
48 return UnlinkedExprOperation.add; | |
49 case QUESTION_QUESTION_TOKEN: | |
50 return UnlinkedExprOperation.ifNull; | |
51 case SLASH_TOKEN: | |
52 return UnlinkedExprOperation.divide; | |
53 case STAR_TOKEN: | |
54 return UnlinkedExprOperation.multiply; | |
55 case TILDE_SLASH_TOKEN: | |
56 return UnlinkedExprOperation.floorDivide; | |
57 default: | |
58 throw "Unhandled openratorKind $operatorKind"; | |
59 } | |
60 } | |
61 | |
62 /// Translate a parser unary operation into an operation in the summary format. | |
63 UnlinkedExprOperation _unaryOpFor(int operatorKind) { | |
64 switch (operatorKind) { | |
65 case BANG_TOKEN: | |
66 return UnlinkedExprOperation.not; | |
67 case MINUS_TOKEN: | |
68 return UnlinkedExprOperation.negate; | |
69 default: | |
70 throw "Unhandled operator kind $operatorKind"; | |
71 } | |
72 } | |
73 | |
74 /// Visitor over the minimal expression AST to convert them into stack-like | |
75 /// expressions used in the summary format. | |
76 class Serializer extends RecursiveVisitor { | |
77 UnlinkedExprBuilder expression; | |
78 final Scope scope; | |
79 final bool forConst; | |
80 | |
81 Serializer(this.scope, this.forConst); | |
82 | |
83 handleAs(As n) { | |
84 throw new UnimplementedError(); // TODO(paulberry): fix the code below. | |
85 // handleType(a.type); | |
86 // expression.operations.add(UnlinkedExprOperation.typeCast); | |
87 } | |
88 | |
89 handleBinary(Binary n) { | |
90 expression.operations.add(_binaryOpFor(n.operator)); | |
91 } | |
92 | |
93 handleBool(BoolLiteral n) { | |
94 expression.operations.add(n.value | |
95 ? UnlinkedExprOperation.pushTrue | |
96 : UnlinkedExprOperation.pushFalse); | |
97 } | |
98 | |
99 handleConditional(Conditional n) { | |
100 expression.operations.add(UnlinkedExprOperation.conditional); | |
101 } | |
102 | |
103 handleConstCreation(ConstCreation n) { | |
104 var ctor = n.constructor; | |
105 var type = handleType(ctor.type); | |
106 if (ctor.name != null) { | |
107 throw new UnimplementedError(); // TODO(paulberry): fix the code below. | |
108 //var classRef = handleRef(ctor.type.name, push: false); | |
109 //var top = scope.top; | |
110 //var ref = new LazyEntityRef(ctor.name, top) | |
111 // ..reference = (scope.serializeReference(classRef.reference, ctor.name)
) | |
112 // ..typeArguments = type.typeArguments | |
113 // ..wasExpanded = true; | |
114 //expression.references.add(ref); | |
115 } else { | |
116 expression.references.add(type); | |
117 } | |
118 expression.ints.add(n.namedArgs.length); | |
119 expression.ints.add(n.positionalArgs.length); | |
120 expression.strings.addAll(n.namedArgs.map((a) => a.name)); | |
121 expression.operations.add(UnlinkedExprOperation.invokeConstructor); | |
122 } | |
123 | |
124 handleDouble(DoubleLiteral n) { | |
125 expression.operations.add(UnlinkedExprOperation.pushDouble); | |
126 expression.doubles.add(n.value); | |
127 } | |
128 | |
129 handleIdentical(Identical n) { | |
130 expression.references.add(handleRef(new Ref('identical'), push: false)); | |
131 expression.ints.add(0); | |
132 expression.ints.add(2); | |
133 expression.ints.add(0); | |
134 expression.operations.add(UnlinkedExprOperation.invokeMethodRef); | |
135 } | |
136 | |
137 handleInt(IntLiteral n) { | |
138 var ints = expression.ints; | |
139 var operations = expression.operations; | |
140 int value = n.value; | |
141 assert(value >= 0); | |
142 if (value >= (1 << 32)) { | |
143 int numOfComponents = 0; | |
144 expression.ints.add(numOfComponents); | |
145 void pushComponents(int value) { | |
146 if (value >= (1 << 32)) { | |
147 pushComponents(value >> 32); | |
148 } | |
149 numOfComponents++; | |
150 ints.add(value & 0xFFFFFFFF); | |
151 } | |
152 | |
153 pushComponents(value); | |
154 ints[ints.length - 1 - numOfComponents] = numOfComponents; | |
155 operations.add(UnlinkedExprOperation.pushLongInt); | |
156 } else { | |
157 operations.add(UnlinkedExprOperation.pushInt); | |
158 ints.add(value); | |
159 } | |
160 } | |
161 | |
162 handleInvalid(Invalid n) { | |
163 expression.isValidConst = false; | |
164 throw new UnimplementedError(); // TODO(paulberry): fix the code below. | |
165 // expression.operations.add(UnlinkedExprOperation.pushInvalidor); | |
166 } | |
167 | |
168 handleIs(Is n) { | |
169 throw new UnimplementedError(); // TODO(paulberry): fix the code below. | |
170 // handleType(i.type); | |
171 // expression.operations.add(UnlinkedExprOperation.typeCheck); | |
172 } | |
173 | |
174 handleList(ListLiteral n) { | |
175 expression.ints.add(n.values.length); | |
176 if (n.elementType == null) { | |
177 expression.operations.add(UnlinkedExprOperation.makeUntypedList); | |
178 } else { | |
179 handleType(n.elementType); | |
180 expression.operations.add(UnlinkedExprOperation.makeTypedList); | |
181 } | |
182 } | |
183 | |
184 handleLoad(Load n) { | |
185 expression.strings.add(n.name); | |
186 expression.operations.add(UnlinkedExprOperation.extractProperty); | |
187 } | |
188 | |
189 handleMap(MapLiteral n) { | |
190 expression.ints.add(n.values.length); | |
191 if (n.types.isEmpty) { | |
192 expression.operations.add(UnlinkedExprOperation.makeUntypedMap); | |
193 } else { | |
194 n.types.forEach(handleType); | |
195 expression.operations.add(UnlinkedExprOperation.makeTypedMap); | |
196 } | |
197 } | |
198 | |
199 handleNull(NullLiteral n) { | |
200 expression.operations.add(UnlinkedExprOperation.pushNull); | |
201 } | |
202 | |
203 handleOpaque(Opaque n) { | |
204 if (n.type != null) { | |
205 handleType(n.type); | |
206 expression.operations.add(UnlinkedExprOperation.pushTypedAbstract); | |
207 } else { | |
208 expression.operations.add(UnlinkedExprOperation.pushUntypedAbstract); | |
209 } | |
210 } | |
211 | |
212 handleOpaqueOp(OpaqueOp n) { | |
213 // nothing to do, recursive visitor serialized subexpression. | |
214 } | |
215 | |
216 handleRef(Ref n, {push: true}) { | |
217 var ref = n.prefix == null | |
218 ? new LazyEntityRef(n.name, scope) | |
219 : new NestedLazyEntityRef( | |
220 handleRef(n.prefix, push: false), n.name, scope); | |
221 if (push) { | |
222 expression.references.add(ref); | |
223 expression.operations.add(UnlinkedExprOperation.pushReference); | |
224 } | |
225 return ref; | |
226 } | |
227 | |
228 handleString(StringLiteral n) { | |
229 expression.strings.add(n.value); | |
230 expression.operations.add(UnlinkedExprOperation.pushString); | |
231 } | |
232 | |
233 handleSymbol(SymbolLiteral n) { | |
234 expression.strings.add(n.value); | |
235 expression.operations.add(UnlinkedExprOperation.makeSymbol); | |
236 } | |
237 | |
238 handleType(TypeRef n) { | |
239 var t = handleRef(n.name, push: false); | |
240 var args = n.typeArguments ?? []; | |
241 t.typeArguments = args.map((a) => handleType(a)).toList(); | |
242 return t; | |
243 } | |
244 | |
245 handleUnary(Unary n) { | |
246 expression.operations.add(_unaryOpFor(n.operator)); | |
247 } | |
248 | |
249 run(Expression root) { | |
250 expression = new UnlinkedExprBuilder( | |
251 isValidConst: forConst, | |
252 operations: [], | |
253 assignmentOperators: [], | |
254 ints: [], | |
255 doubles: [], | |
256 strings: [], | |
257 references: []); | |
258 root.accept(this); | |
259 expression.references.forEach((r) => (r as LazyEntityRef).expand()); | |
260 return expression; | |
261 } | |
262 } | |
OLD | NEW |