| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // Note: copied from package:kernel at revision 7346348. | 5 // Note: copied from package:kernel at revision 7346348. |
| 6 | 6 |
| 7 /// A library to help transform compounds and null-aware accessors into | 7 /// A library to help transform compounds and null-aware accessors into |
| 8 /// let expressions. | 8 /// let expressions. |
| 9 library kernel.frontend.accessors; | 9 library kernel.frontend.accessors; |
| 10 | 10 |
| 11 import 'package:kernel/ast.dart'; | 11 import 'package:kernel/ast.dart'; |
| 12 | 12 |
| 13 import '../names.dart' show indexGetName, indexSetName; |
| 14 |
| 13 /// An [Accessor] represents a subexpression for which we can't yet build a | 15 /// An [Accessor] represents a subexpression for which we can't yet build a |
| 14 /// kernel [Expression] because we don't yet know the context in which it is | 16 /// kernel [Expression] because we don't yet know the context in which it is |
| 15 /// used. | 17 /// used. |
| 16 /// | 18 /// |
| 17 /// Once the context is known, an [Accessor] can be converted into an | 19 /// Once the context is known, an [Accessor] can be converted into an |
| 18 /// [Expression] by calling a "build" method. | 20 /// [Expression] by calling a "build" method. |
| 19 /// | 21 /// |
| 20 /// For example, when building a kernel representation for `a[x] = b`, after | 22 /// For example, when building a kernel representation for `a[x] = b`, after |
| 21 /// parsing `a[x]` but before parsing `= b`, we don't yet know whether to | 23 /// parsing `a[x]` but before parsing `= b`, we don't yet know whether to |
| 22 /// generate an invocation of `operator[]` or `operator[]=`, so we generate an | 24 /// generate an invocation of `operator[]` or `operator[]=`, so we generate an |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 _makeWrite(Expression value, bool voidContext) { | 243 _makeWrite(Expression value, bool voidContext) { |
| 242 if (setter == null) return makeInvalidWrite(value); | 244 if (setter == null) return makeInvalidWrite(value); |
| 243 // TODO(ahe): Use [DirectPropertySet] when possible. | 245 // TODO(ahe): Use [DirectPropertySet] when possible. |
| 244 Expression result = new DirectPropertySet( | 246 Expression result = new DirectPropertySet( |
| 245 new ThisExpression(), setter, value)..fileOffset = charOffset; | 247 new ThisExpression(), setter, value)..fileOffset = charOffset; |
| 246 result = new SuperPropertySet(name, value, setter)..fileOffset = charOffset; | 248 result = new SuperPropertySet(name, value, setter)..fileOffset = charOffset; |
| 247 return result; | 249 return result; |
| 248 } | 250 } |
| 249 } | 251 } |
| 250 | 252 |
| 251 final Name _indexGet = new Name('[]'); | |
| 252 final Name _indexSet = new Name('[]='); | |
| 253 | |
| 254 class IndexAccessor extends Accessor { | 253 class IndexAccessor extends Accessor { |
| 255 Expression receiver; | 254 Expression receiver; |
| 256 Expression index; | 255 Expression index; |
| 257 VariableDeclaration receiverVariable; | 256 VariableDeclaration receiverVariable; |
| 258 VariableDeclaration indexVariable; | 257 VariableDeclaration indexVariable; |
| 259 Procedure getter, setter; | 258 Procedure getter, setter; |
| 260 int charOffset; | 259 int charOffset; |
| 261 | 260 |
| 262 static Accessor make(Expression receiver, Expression index, Procedure getter, | 261 static Accessor make(Expression receiver, Expression index, Procedure getter, |
| 263 Procedure setter, int charOffset) { | 262 Procedure setter, int charOffset) { |
| 264 if (receiver is ThisExpression) { | 263 if (receiver is ThisExpression) { |
| 265 return new ThisIndexAccessor(index, getter, setter); | 264 return new ThisIndexAccessor(index, getter, setter); |
| 266 } else { | 265 } else { |
| 267 return new IndexAccessor.internal( | 266 return new IndexAccessor.internal( |
| 268 receiver, index, getter, setter, charOffset); | 267 receiver, index, getter, setter, charOffset); |
| 269 } | 268 } |
| 270 } | 269 } |
| 271 | 270 |
| 272 IndexAccessor.internal( | 271 IndexAccessor.internal( |
| 273 this.receiver, this.index, this.getter, this.setter, this.charOffset); | 272 this.receiver, this.index, this.getter, this.setter, this.charOffset); |
| 274 | 273 |
| 275 _makeSimpleRead() => new MethodInvocation( | 274 _makeSimpleRead() => new MethodInvocation( |
| 276 receiver, _indexGet, new Arguments(<Expression>[index]), getter) | 275 receiver, indexGetName, new Arguments(<Expression>[index]), getter) |
| 277 ..fileOffset = charOffset; | 276 ..fileOffset = charOffset; |
| 278 | 277 |
| 279 _makeSimpleWrite(Expression value, bool voidContext) { | 278 _makeSimpleWrite(Expression value, bool voidContext) { |
| 280 if (!voidContext) return _makeWriteAndReturn(value); | 279 if (!voidContext) return _makeWriteAndReturn(value); |
| 281 return new MethodInvocation( | 280 return new MethodInvocation( |
| 282 receiver, _indexSet, new Arguments(<Expression>[index, value]), setter) | 281 receiver, |
| 283 ..fileOffset = charOffset; | 282 indexSetName, |
| 283 new Arguments(<Expression>[index, value]), |
| 284 setter)..fileOffset = charOffset; |
| 284 } | 285 } |
| 285 | 286 |
| 286 receiverAccess() { | 287 receiverAccess() { |
| 287 // We cannot reuse the receiver if it is a variable since it might be | 288 // We cannot reuse the receiver if it is a variable since it might be |
| 288 // reassigned in the index expression. | 289 // reassigned in the index expression. |
| 289 receiverVariable ??= new VariableDeclaration.forValue(receiver); | 290 receiverVariable ??= new VariableDeclaration.forValue(receiver); |
| 290 return new VariableGet(receiverVariable)..fileOffset = charOffset; | 291 return new VariableGet(receiverVariable)..fileOffset = charOffset; |
| 291 } | 292 } |
| 292 | 293 |
| 293 indexAccess() { | 294 indexAccess() { |
| 294 indexVariable ??= new VariableDeclaration.forValue(index); | 295 indexVariable ??= new VariableDeclaration.forValue(index); |
| 295 return new VariableGet(indexVariable)..fileOffset = charOffset; | 296 return new VariableGet(indexVariable)..fileOffset = charOffset; |
| 296 } | 297 } |
| 297 | 298 |
| 298 _makeRead() { | 299 _makeRead() { |
| 299 return new MethodInvocation( | 300 return new MethodInvocation( |
| 300 receiverAccess(), | 301 receiverAccess(), |
| 301 _indexGet, | 302 indexGetName, |
| 302 new Arguments(<Expression>[indexAccess()]), | 303 new Arguments(<Expression>[indexAccess()]), |
| 303 getter)..fileOffset = charOffset; | 304 getter)..fileOffset = charOffset; |
| 304 } | 305 } |
| 305 | 306 |
| 306 _makeWrite(Expression value, bool voidContext) { | 307 _makeWrite(Expression value, bool voidContext) { |
| 307 if (!voidContext) return _makeWriteAndReturn(value); | 308 if (!voidContext) return _makeWriteAndReturn(value); |
| 308 return new MethodInvocation( | 309 return new MethodInvocation( |
| 309 receiverAccess(), | 310 receiverAccess(), |
| 310 _indexSet, | 311 indexSetName, |
| 311 new Arguments(<Expression>[indexAccess(), value]), | 312 new Arguments(<Expression>[indexAccess(), value]), |
| 312 setter)..fileOffset = charOffset; | 313 setter)..fileOffset = charOffset; |
| 313 } | 314 } |
| 314 | 315 |
| 315 _makeWriteAndReturn(Expression value) { | 316 _makeWriteAndReturn(Expression value) { |
| 316 // The call to []= does not return the value like direct-style assignments | 317 // The call to []= does not return the value like direct-style assignments |
| 317 // do. We need to bind the value in a let. | 318 // do. We need to bind the value in a let. |
| 318 var valueVariable = new VariableDeclaration.forValue(value); | 319 var valueVariable = new VariableDeclaration.forValue(value); |
| 319 var dummy = new VariableDeclaration.forValue(new MethodInvocation( | 320 var dummy = new VariableDeclaration.forValue(new MethodInvocation( |
| 320 receiverAccess(), | 321 receiverAccess(), |
| 321 _indexSet, | 322 indexSetName, |
| 322 new Arguments( | 323 new Arguments( |
| 323 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 324 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
| 324 setter)..fileOffset = charOffset); | 325 setter)..fileOffset = charOffset); |
| 325 return makeLet( | 326 return makeLet( |
| 326 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 327 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
| 327 } | 328 } |
| 328 | 329 |
| 329 Expression _finish(Expression body) { | 330 Expression _finish(Expression body) { |
| 330 return makeLet(receiverVariable, makeLet(indexVariable, body)); | 331 return makeLet(receiverVariable, makeLet(indexVariable, body)); |
| 331 } | 332 } |
| 332 } | 333 } |
| 333 | 334 |
| 334 /// Special case of [IndexAccessor] to avoid creating an indirect access to | 335 /// Special case of [IndexAccessor] to avoid creating an indirect access to |
| 335 /// 'this'. | 336 /// 'this'. |
| 336 class ThisIndexAccessor extends Accessor { | 337 class ThisIndexAccessor extends Accessor { |
| 337 Expression index; | 338 Expression index; |
| 338 VariableDeclaration indexVariable; | 339 VariableDeclaration indexVariable; |
| 339 Procedure getter, setter; | 340 Procedure getter, setter; |
| 340 | 341 |
| 341 ThisIndexAccessor(this.index, this.getter, this.setter); | 342 ThisIndexAccessor(this.index, this.getter, this.setter); |
| 342 | 343 |
| 343 _makeSimpleRead() { | 344 _makeSimpleRead() { |
| 344 return new MethodInvocation(new ThisExpression(), _indexGet, | 345 return new MethodInvocation(new ThisExpression(), indexGetName, |
| 345 new Arguments(<Expression>[index]), getter); | 346 new Arguments(<Expression>[index]), getter); |
| 346 } | 347 } |
| 347 | 348 |
| 348 _makeSimpleWrite(Expression value, bool voidContext) { | 349 _makeSimpleWrite(Expression value, bool voidContext) { |
| 349 if (!voidContext) return _makeWriteAndReturn(value); | 350 if (!voidContext) return _makeWriteAndReturn(value); |
| 350 return new MethodInvocation(new ThisExpression(), _indexSet, | 351 return new MethodInvocation(new ThisExpression(), indexSetName, |
| 351 new Arguments(<Expression>[index, value]), setter); | 352 new Arguments(<Expression>[index, value]), setter); |
| 352 } | 353 } |
| 353 | 354 |
| 354 indexAccess() { | 355 indexAccess() { |
| 355 indexVariable ??= new VariableDeclaration.forValue(index); | 356 indexVariable ??= new VariableDeclaration.forValue(index); |
| 356 return new VariableGet(indexVariable); | 357 return new VariableGet(indexVariable); |
| 357 } | 358 } |
| 358 | 359 |
| 359 _makeRead() => new MethodInvocation(new ThisExpression(), _indexGet, | 360 _makeRead() => new MethodInvocation(new ThisExpression(), indexGetName, |
| 360 new Arguments(<Expression>[indexAccess()]), getter); | 361 new Arguments(<Expression>[indexAccess()]), getter); |
| 361 | 362 |
| 362 _makeWrite(Expression value, bool voidContext) { | 363 _makeWrite(Expression value, bool voidContext) { |
| 363 if (!voidContext) return _makeWriteAndReturn(value); | 364 if (!voidContext) return _makeWriteAndReturn(value); |
| 364 return new MethodInvocation(new ThisExpression(), _indexSet, | 365 return new MethodInvocation(new ThisExpression(), indexSetName, |
| 365 new Arguments(<Expression>[indexAccess(), value]), setter); | 366 new Arguments(<Expression>[indexAccess(), value]), setter); |
| 366 } | 367 } |
| 367 | 368 |
| 368 _makeWriteAndReturn(Expression value) { | 369 _makeWriteAndReturn(Expression value) { |
| 369 var valueVariable = new VariableDeclaration.forValue(value); | 370 var valueVariable = new VariableDeclaration.forValue(value); |
| 370 var dummy = new VariableDeclaration.forValue(new MethodInvocation( | 371 var dummy = new VariableDeclaration.forValue(new MethodInvocation( |
| 371 new ThisExpression(), | 372 new ThisExpression(), |
| 372 _indexSet, | 373 indexSetName, |
| 373 new Arguments( | 374 new Arguments( |
| 374 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 375 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
| 375 setter)); | 376 setter)); |
| 376 return makeLet( | 377 return makeLet( |
| 377 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 378 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
| 378 } | 379 } |
| 379 | 380 |
| 380 Expression _finish(Expression body) => makeLet(indexVariable, body); | 381 Expression _finish(Expression body) => makeLet(indexVariable, body); |
| 381 } | 382 } |
| 382 | 383 |
| 383 class SuperIndexAccessor extends Accessor { | 384 class SuperIndexAccessor extends Accessor { |
| 384 Expression index; | 385 Expression index; |
| 385 VariableDeclaration indexVariable; | 386 VariableDeclaration indexVariable; |
| 386 Member getter, setter; | 387 Member getter, setter; |
| 387 | 388 |
| 388 SuperIndexAccessor(this.index, this.getter, this.setter); | 389 SuperIndexAccessor(this.index, this.getter, this.setter); |
| 389 | 390 |
| 390 indexAccess() { | 391 indexAccess() { |
| 391 indexVariable ??= new VariableDeclaration.forValue(index); | 392 indexVariable ??= new VariableDeclaration.forValue(index); |
| 392 return new VariableGet(indexVariable); | 393 return new VariableGet(indexVariable); |
| 393 } | 394 } |
| 394 | 395 |
| 395 _makeSimpleRead() => new SuperMethodInvocation( | 396 _makeSimpleRead() => new SuperMethodInvocation( |
| 396 _indexGet, new Arguments(<Expression>[index]), getter); | 397 indexGetName, new Arguments(<Expression>[index]), getter); |
| 397 | 398 |
| 398 _makeSimpleWrite(Expression value, bool voidContext) { | 399 _makeSimpleWrite(Expression value, bool voidContext) { |
| 399 if (!voidContext) return _makeWriteAndReturn(value); | 400 if (!voidContext) return _makeWriteAndReturn(value); |
| 400 return new SuperMethodInvocation( | 401 return new SuperMethodInvocation( |
| 401 _indexSet, new Arguments(<Expression>[index, value]), setter); | 402 indexSetName, new Arguments(<Expression>[index, value]), setter); |
| 402 } | 403 } |
| 403 | 404 |
| 404 _makeRead() { | 405 _makeRead() { |
| 405 return new SuperMethodInvocation( | 406 return new SuperMethodInvocation( |
| 406 _indexGet, new Arguments(<Expression>[indexAccess()]), getter); | 407 indexGetName, new Arguments(<Expression>[indexAccess()]), getter); |
| 407 } | 408 } |
| 408 | 409 |
| 409 _makeWrite(Expression value, bool voidContext) { | 410 _makeWrite(Expression value, bool voidContext) { |
| 410 if (!voidContext) return _makeWriteAndReturn(value); | 411 if (!voidContext) return _makeWriteAndReturn(value); |
| 411 return new SuperMethodInvocation( | 412 return new SuperMethodInvocation(indexSetName, |
| 412 _indexSet, new Arguments(<Expression>[indexAccess(), value]), setter); | 413 new Arguments(<Expression>[indexAccess(), value]), setter); |
| 413 } | 414 } |
| 414 | 415 |
| 415 _makeWriteAndReturn(Expression value) { | 416 _makeWriteAndReturn(Expression value) { |
| 416 var valueVariable = new VariableDeclaration.forValue(value); | 417 var valueVariable = new VariableDeclaration.forValue(value); |
| 417 var dummy = new VariableDeclaration.forValue(new SuperMethodInvocation( | 418 var dummy = new VariableDeclaration.forValue(new SuperMethodInvocation( |
| 418 _indexSet, | 419 indexSetName, |
| 419 new Arguments( | 420 new Arguments( |
| 420 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 421 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
| 421 setter)); | 422 setter)); |
| 422 return makeLet( | 423 return makeLet( |
| 423 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 424 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
| 424 } | 425 } |
| 425 | 426 |
| 426 Expression _finish(Expression body) { | 427 Expression _finish(Expression body) { |
| 427 return makeLet(indexVariable, body); | 428 return makeLet(indexVariable, body); |
| 428 } | 429 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 | 486 |
| 486 VariableDeclaration makeOrReuseVariable(Expression value) { | 487 VariableDeclaration makeOrReuseVariable(Expression value) { |
| 487 // TODO: Devise a way to remember if a variable declaration was reused | 488 // TODO: Devise a way to remember if a variable declaration was reused |
| 488 // or is fresh (hence needs a let binding). | 489 // or is fresh (hence needs a let binding). |
| 489 return new VariableDeclaration.forValue(value); | 490 return new VariableDeclaration.forValue(value); |
| 490 } | 491 } |
| 491 | 492 |
| 492 Expression wrapInvalid(Expression e) { | 493 Expression wrapInvalid(Expression e) { |
| 493 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); | 494 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); |
| 494 } | 495 } |
| OLD | NEW |