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

Side by Side Diff: pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart

Issue 2777883002: Remove Fasta's copy of accessors.dart. (Closed)
Patch Set: Created 3 years, 8 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2016, 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 // Note: copied from package:kernel at revision 7346348.
6
7 /// A library to help transform compounds and null-aware accessors into
8 /// let expressions.
9 library kernel.frontend.accessors;
10
11 import 'package:kernel/ast.dart';
12
13 import '../names.dart' show indexGetName, indexSetName;
14
15 /// An [Accessor] represents a subexpression for which we can't yet build a
16 /// kernel [Expression] because we don't yet know the context in which it is
17 /// used.
18 ///
19 /// Once the context is known, an [Accessor] can be converted into an
20 /// [Expression] by calling a "build" method.
21 ///
22 /// For example, when building a kernel representation for `a[x] = b`, after
23 /// parsing `a[x]` but before parsing `= b`, we don't yet know whether to
24 /// generate an invocation of `operator[]` or `operator[]=`, so we generate an
25 /// [Accessor] object. Later, after `= b` is parsed, [buildAssignment] will be
26 /// called.
27 abstract class Accessor {
28 /// Builds an [Expression] representing a read from the accessor.
29 Expression buildSimpleRead() {
30 return _finish(_makeSimpleRead());
31 }
32
33 /// Builds an [Expression] representing an assignment with the accessor on
34 /// the LHS and [value] on the RHS.
35 ///
36 /// The returned expression evaluates to the assigned value, unless
37 /// [voidContext] is true, in which case it may evaluate to anything.
38 Expression buildAssignment(Expression value, {bool voidContext: false}) {
39 return _finish(_makeSimpleWrite(value, voidContext));
40 }
41
42 /// Returns an [Expression] representing a null-aware assignment (`??=`) with
43 /// the accessor on the LHS and [value] on the RHS.
44 ///
45 /// The returned expression evaluates to the assigned value, unless
46 /// [voidContext] is true, in which case it may evaluate to anything.
47 ///
48 /// [type] is the static type of the RHS.
49 Expression buildNullAwareAssignment(Expression value, DartType type,
50 {bool voidContext: false}) {
51 if (voidContext) {
52 return _finish(new ConditionalExpression(buildIsNull(_makeRead()),
53 _makeWrite(value, false), new NullLiteral(), type));
54 }
55 var tmp = new VariableDeclaration.forValue(_makeRead());
56 return _finish(makeLet(
57 tmp,
58 new ConditionalExpression(buildIsNull(new VariableGet(tmp)),
59 _makeWrite(value, false), new VariableGet(tmp), type)));
60 }
61
62 /// Returns an [Expression] representing a compound assignment (e.g. `+=`)
63 /// with the accessor on the LHS and [value] on the RHS.
64 Expression buildCompoundAssignment(
65 Name binaryOperator, Expression value, int charOffset,
66 {bool voidContext: false, Procedure interfaceTarget}) {
67 return _finish(_makeWrite(
68 makeBinary(
69 _makeRead(), binaryOperator, interfaceTarget, value, charOffset),
70 voidContext));
71 }
72
73 /// Returns an [Expression] representing a pre-increment or pre-decrement
74 /// of the accessor.
75 Expression buildPrefixIncrement(Name binaryOperator, int charOffset,
76 {bool voidContext: false, Procedure interfaceTarget}) {
77 return buildCompoundAssignment(
78 binaryOperator, new IntLiteral(1), charOffset,
79 voidContext: voidContext, interfaceTarget: interfaceTarget);
80 }
81
82 /// Returns an [Expression] representing a post-increment or post-decrement
83 /// of the accessor.
84 Expression buildPostfixIncrement(Name binaryOperator, int charOffset,
85 {bool voidContext: false, Procedure interfaceTarget}) {
86 if (voidContext) {
87 return buildPrefixIncrement(binaryOperator, charOffset,
88 voidContext: true, interfaceTarget: interfaceTarget);
89 }
90 var value = new VariableDeclaration.forValue(_makeRead());
91 valueAccess() => new VariableGet(value);
92 var dummy = new VariableDeclaration.forValue(_makeWrite(
93 makeBinary(valueAccess(), binaryOperator, interfaceTarget,
94 new IntLiteral(1), charOffset),
95 true));
96 return _finish(makeLet(value, makeLet(dummy, valueAccess())));
97 }
98
99 Expression _makeSimpleRead() => _makeRead();
100
101 Expression _makeSimpleWrite(Expression value, bool voidContext) {
102 return _makeWrite(value, voidContext);
103 }
104
105 Expression _makeRead();
106
107 Expression _makeWrite(Expression value, bool voidContext);
108
109 Expression _finish(Expression body) => body;
110
111 /// Returns an [Expression] representing a compile-time error.
112 ///
113 /// At runtime, an exception will be thrown.
114 makeInvalidRead() => new InvalidExpression();
115
116 /// Returns an [Expression] representing a compile-time error wrapping
117 /// [value].
118 ///
119 /// At runtime, [value] will be evaluated before throwing an exception.
120 makeInvalidWrite(Expression value) => wrapInvalid(value);
121 }
122
123 class VariableAccessor extends Accessor {
124 VariableDeclaration variable;
125 int charOffset;
126 DartType promotedType;
127
128 VariableAccessor(this.variable, [this.promotedType]);
129
130 VariableAccessor.internal(this.variable, this.charOffset, this.promotedType);
131
132 _makeRead() =>
133 new VariableGet(variable, promotedType)..fileOffset = charOffset;
134
135 _makeWrite(Expression value, bool voidContext) {
136 return variable.isFinal || variable.isConst
137 ? makeInvalidWrite(value)
138 : new VariableSet(variable, value)..fileOffset = charOffset;
139 }
140 }
141
142 class PropertyAccessor extends Accessor {
143 VariableDeclaration _receiverVariable;
144 Expression receiver;
145 Name name;
146 Member getter, setter;
147 int charOffset;
148
149 static Accessor make(Expression receiver, Name name, Member getter,
150 Member setter, int charOffset) {
151 if (receiver is ThisExpression) {
152 return new ThisPropertyAccessor(name, getter, setter, charOffset);
153 } else {
154 return new PropertyAccessor.internal(
155 receiver, name, getter, setter, charOffset);
156 }
157 }
158
159 PropertyAccessor.internal(
160 this.receiver, this.name, this.getter, this.setter, this.charOffset);
161
162 _makeSimpleRead() =>
163 new PropertyGet(receiver, name, getter)..fileOffset = charOffset;
164 _makeSimpleWrite(Expression value, bool voidContext) {
165 return new PropertySet(receiver, name, value, setter)
166 ..fileOffset = charOffset;
167 }
168
169 receiverAccess() {
170 _receiverVariable ??= new VariableDeclaration.forValue(receiver);
171 return new VariableGet(_receiverVariable)..fileOffset = charOffset;
172 }
173
174 _makeRead() =>
175 new PropertyGet(receiverAccess(), name, getter)..fileOffset = charOffset;
176
177 _makeWrite(Expression value, bool voidContext) {
178 return new PropertySet(receiverAccess(), name, value, setter)
179 ..fileOffset = charOffset;
180 }
181
182 _finish(Expression body) => makeLet(_receiverVariable, body);
183 }
184
185 /// Special case of [PropertyAccessor] to avoid creating an indirect access to
186 /// 'this'.
187 class ThisPropertyAccessor extends Accessor {
188 Name name;
189 Member getter, setter;
190 final int charOffset;
191
192 ThisPropertyAccessor(this.name, this.getter, this.setter, this.charOffset);
193
194 _makeRead() => new PropertyGet(new ThisExpression(), name, getter)
195 ..fileOffset = charOffset;
196
197 _makeWrite(Expression value, bool voidContext) {
198 return new PropertySet(new ThisExpression(), name, value, setter)
199 ..fileOffset = charOffset;
200 }
201 }
202
203 class NullAwarePropertyAccessor extends Accessor {
204 VariableDeclaration receiver;
205 Name name;
206 Member getter, setter;
207 DartType type;
208
209 NullAwarePropertyAccessor(
210 Expression receiver, this.name, this.getter, this.setter, this.type)
211 : this.receiver = makeOrReuseVariable(receiver);
212
213 receiverAccess() => new VariableGet(receiver);
214
215 _makeRead() => new PropertyGet(receiverAccess(), name, getter);
216
217 _makeWrite(Expression value, bool voidContext) {
218 return new PropertySet(receiverAccess(), name, value, setter);
219 }
220
221 _finish(Expression body) => makeLet(
222 receiver,
223 new ConditionalExpression(
224 buildIsNull(receiverAccess()), new NullLiteral(), body, type));
225 }
226
227 class SuperPropertyAccessor extends Accessor {
228 Name name;
229 Member getter, setter;
230 final int charOffset;
231
232 SuperPropertyAccessor(this.name, this.getter, this.setter, this.charOffset);
233
234 _makeRead() {
235 if (getter == null) return makeInvalidRead();
236 // TODO(ahe): Use [DirectPropertyGet] when possible.
237 Expression result = new DirectPropertyGet(new ThisExpression(), getter)
238 ..fileOffset = charOffset;
239 result = new SuperPropertyGet(name, getter)..fileOffset = charOffset;
240 return result;
241 }
242
243 _makeWrite(Expression value, bool voidContext) {
244 if (setter == null) return makeInvalidWrite(value);
245 // TODO(ahe): Use [DirectPropertySet] when possible.
246 Expression result = new DirectPropertySet(
247 new ThisExpression(), setter, value)..fileOffset = charOffset;
248 result = new SuperPropertySet(name, value, setter)..fileOffset = charOffset;
249 return result;
250 }
251 }
252
253 class IndexAccessor extends Accessor {
254 Expression receiver;
255 Expression index;
256 VariableDeclaration receiverVariable;
257 VariableDeclaration indexVariable;
258 Procedure getter, setter;
259 int charOffset;
260
261 static Accessor make(Expression receiver, Expression index, Procedure getter,
262 Procedure setter, int charOffset) {
263 if (receiver is ThisExpression) {
264 return new ThisIndexAccessor(index, getter, setter);
265 } else {
266 return new IndexAccessor.internal(
267 receiver, index, getter, setter, charOffset);
268 }
269 }
270
271 IndexAccessor.internal(
272 this.receiver, this.index, this.getter, this.setter, this.charOffset);
273
274 _makeSimpleRead() => new MethodInvocation(
275 receiver, indexGetName, new Arguments(<Expression>[index]), getter)
276 ..fileOffset = charOffset;
277
278 _makeSimpleWrite(Expression value, bool voidContext) {
279 if (!voidContext) return _makeWriteAndReturn(value);
280 return new MethodInvocation(
281 receiver,
282 indexSetName,
283 new Arguments(<Expression>[index, value]),
284 setter)..fileOffset = charOffset;
285 }
286
287 receiverAccess() {
288 // We cannot reuse the receiver if it is a variable since it might be
289 // reassigned in the index expression.
290 receiverVariable ??= new VariableDeclaration.forValue(receiver);
291 return new VariableGet(receiverVariable)..fileOffset = charOffset;
292 }
293
294 indexAccess() {
295 indexVariable ??= new VariableDeclaration.forValue(index);
296 return new VariableGet(indexVariable)..fileOffset = charOffset;
297 }
298
299 _makeRead() {
300 return new MethodInvocation(
301 receiverAccess(),
302 indexGetName,
303 new Arguments(<Expression>[indexAccess()]),
304 getter)..fileOffset = charOffset;
305 }
306
307 _makeWrite(Expression value, bool voidContext) {
308 if (!voidContext) return _makeWriteAndReturn(value);
309 return new MethodInvocation(
310 receiverAccess(),
311 indexSetName,
312 new Arguments(<Expression>[indexAccess(), value]),
313 setter)..fileOffset = charOffset;
314 }
315
316 _makeWriteAndReturn(Expression value) {
317 // The call to []= does not return the value like direct-style assignments
318 // do. We need to bind the value in a let.
319 var valueVariable = new VariableDeclaration.forValue(value);
320 var dummy = new VariableDeclaration.forValue(new MethodInvocation(
321 receiverAccess(),
322 indexSetName,
323 new Arguments(
324 <Expression>[indexAccess(), new VariableGet(valueVariable)]),
325 setter)..fileOffset = charOffset);
326 return makeLet(
327 valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
328 }
329
330 Expression _finish(Expression body) {
331 return makeLet(receiverVariable, makeLet(indexVariable, body));
332 }
333 }
334
335 /// Special case of [IndexAccessor] to avoid creating an indirect access to
336 /// 'this'.
337 class ThisIndexAccessor extends Accessor {
338 Expression index;
339 VariableDeclaration indexVariable;
340 Procedure getter, setter;
341
342 ThisIndexAccessor(this.index, this.getter, this.setter);
343
344 _makeSimpleRead() {
345 return new MethodInvocation(new ThisExpression(), indexGetName,
346 new Arguments(<Expression>[index]), getter);
347 }
348
349 _makeSimpleWrite(Expression value, bool voidContext) {
350 if (!voidContext) return _makeWriteAndReturn(value);
351 return new MethodInvocation(new ThisExpression(), indexSetName,
352 new Arguments(<Expression>[index, value]), setter);
353 }
354
355 indexAccess() {
356 indexVariable ??= new VariableDeclaration.forValue(index);
357 return new VariableGet(indexVariable);
358 }
359
360 _makeRead() => new MethodInvocation(new ThisExpression(), indexGetName,
361 new Arguments(<Expression>[indexAccess()]), getter);
362
363 _makeWrite(Expression value, bool voidContext) {
364 if (!voidContext) return _makeWriteAndReturn(value);
365 return new MethodInvocation(new ThisExpression(), indexSetName,
366 new Arguments(<Expression>[indexAccess(), value]), setter);
367 }
368
369 _makeWriteAndReturn(Expression value) {
370 var valueVariable = new VariableDeclaration.forValue(value);
371 var dummy = new VariableDeclaration.forValue(new MethodInvocation(
372 new ThisExpression(),
373 indexSetName,
374 new Arguments(
375 <Expression>[indexAccess(), new VariableGet(valueVariable)]),
376 setter));
377 return makeLet(
378 valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
379 }
380
381 Expression _finish(Expression body) => makeLet(indexVariable, body);
382 }
383
384 class SuperIndexAccessor extends Accessor {
385 Expression index;
386 VariableDeclaration indexVariable;
387 Member getter, setter;
388
389 SuperIndexAccessor(this.index, this.getter, this.setter);
390
391 indexAccess() {
392 indexVariable ??= new VariableDeclaration.forValue(index);
393 return new VariableGet(indexVariable);
394 }
395
396 _makeSimpleRead() => new SuperMethodInvocation(
397 indexGetName, new Arguments(<Expression>[index]), getter);
398
399 _makeSimpleWrite(Expression value, bool voidContext) {
400 if (!voidContext) return _makeWriteAndReturn(value);
401 return new SuperMethodInvocation(
402 indexSetName, new Arguments(<Expression>[index, value]), setter);
403 }
404
405 _makeRead() {
406 return new SuperMethodInvocation(
407 indexGetName, new Arguments(<Expression>[indexAccess()]), getter);
408 }
409
410 _makeWrite(Expression value, bool voidContext) {
411 if (!voidContext) return _makeWriteAndReturn(value);
412 return new SuperMethodInvocation(indexSetName,
413 new Arguments(<Expression>[indexAccess(), value]), setter);
414 }
415
416 _makeWriteAndReturn(Expression value) {
417 var valueVariable = new VariableDeclaration.forValue(value);
418 var dummy = new VariableDeclaration.forValue(new SuperMethodInvocation(
419 indexSetName,
420 new Arguments(
421 <Expression>[indexAccess(), new VariableGet(valueVariable)]),
422 setter));
423 return makeLet(
424 valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
425 }
426
427 Expression _finish(Expression body) {
428 return makeLet(indexVariable, body);
429 }
430 }
431
432 class StaticAccessor extends Accessor {
433 Member readTarget;
434 Member writeTarget;
435 int charOffset;
436
437 StaticAccessor(this.readTarget, this.writeTarget, this.charOffset);
438
439 _makeRead() =>
440 readTarget == null ? makeInvalidRead() : new StaticGet(readTarget)
441 ..fileOffset = charOffset;
442
443 _makeWrite(Expression value, bool voidContext) {
444 return writeTarget == null
445 ? makeInvalidWrite(value)
446 : new StaticSet(writeTarget, value)..fileOffset = charOffset;
447 }
448 }
449
450 class ReadOnlyAccessor extends Accessor {
451 Expression expression;
452 VariableDeclaration value;
453
454 ReadOnlyAccessor(this.expression);
455
456 _makeSimpleRead() => expression;
457
458 _makeRead() {
459 value ??= new VariableDeclaration.forValue(expression);
460 return new VariableGet(value);
461 }
462
463 _makeWrite(Expression value, bool voidContext) => makeInvalidWrite(value);
464
465 Expression _finish(Expression body) => makeLet(value, body);
466 }
467
468 Expression makeLet(VariableDeclaration variable, Expression body) {
469 if (variable == null) return body;
470 return new Let(variable, body);
471 }
472
473 Expression makeBinary(Expression left, Name operator, Procedure interfaceTarget,
474 Expression right, int charOffset) {
475 return new MethodInvocation(
476 left, operator, new Arguments(<Expression>[right]), interfaceTarget)
477 ..fileOffset = charOffset;
478 }
479
480 final Name _equalOperator = new Name('==');
481
482 Expression buildIsNull(Expression value) {
483 return makeBinary(
484 value, _equalOperator, null, new NullLiteral(), TreeNode.noOffset);
485 }
486
487 VariableDeclaration makeOrReuseVariable(Expression value) {
488 // TODO: Devise a way to remember if a variable declaration was reused
489 // or is fresh (hence needs a let binding).
490 return new VariableDeclaration.forValue(value);
491 }
492
493 Expression wrapInvalid(Expression e) {
494 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression());
495 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698