| 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 /// A library to help transform compounds and null-aware accessors into | 5 /// A library to help transform compounds and null-aware accessors into |
| 6 /// let expressions. | 6 /// let expressions. |
| 7 | 7 |
| 8 import 'package:front_end/src/fasta/scanner/token.dart' |
| 9 show Token, offsetForToken; |
| 10 |
| 8 import 'package:front_end/src/fasta/kernel/fasta_accessors.dart' | 11 import 'package:front_end/src/fasta/kernel/fasta_accessors.dart' |
| 9 show BuilderHelper; | 12 show BuilderHelper; |
| 10 | 13 |
| 11 import 'package:kernel/ast.dart'; | 14 import 'package:kernel/ast.dart'; |
| 12 | 15 |
| 13 final Name indexGetName = new Name("[]"); | 16 final Name indexGetName = new Name("[]"); |
| 14 | 17 |
| 15 final Name indexSetName = new Name("[]="); | 18 final Name indexSetName = new Name("[]="); |
| 16 | 19 |
| 17 /// An [Accessor] represents a subexpression for which we can't yet build a | 20 /// An [Accessor] represents a subexpression for which we can't yet build a |
| 18 /// kernel [Expression] because we don't yet know the context in which it is | 21 /// kernel [Expression] because we don't yet know the context in which it is |
| 19 /// used. | 22 /// used. |
| 20 /// | 23 /// |
| 21 /// Once the context is known, an [Accessor] can be converted into an | 24 /// Once the context is known, an [Accessor] can be converted into an |
| 22 /// [Expression] by calling a "build" method. | 25 /// [Expression] by calling a "build" method. |
| 23 /// | 26 /// |
| 24 /// For example, when building a kernel representation for `a[x] = b`, after | 27 /// For example, when building a kernel representation for `a[x] = b`, after |
| 25 /// parsing `a[x]` but before parsing `= b`, we don't yet know whether to | 28 /// parsing `a[x]` but before parsing `= b`, we don't yet know whether to |
| 26 /// generate an invocation of `operator[]` or `operator[]=`, so we generate an | 29 /// generate an invocation of `operator[]` or `operator[]=`, so we generate an |
| 27 /// [Accessor] object. Later, after `= b` is parsed, [buildAssignment] will be | 30 /// [Accessor] object. Later, after `= b` is parsed, [buildAssignment] will be |
| 28 /// called. | 31 /// called. |
| 29 abstract class Accessor { | 32 abstract class Accessor { |
| 30 final int offset; | 33 final Token token; |
| 31 | 34 |
| 32 // [builtBinary] and [builtGetter] capture the inner nodes. Used by | 35 // [builtBinary] and [builtGetter] capture the inner nodes. Used by |
| 33 // dart2js+rasta for determining how subexpressions map to legacy dart2js Ast | 36 // dart2js+rasta for determining how subexpressions map to legacy dart2js Ast |
| 34 // nodes. This will be removed once dart2js type analysis (aka inference) is | 37 // nodes. This will be removed once dart2js type analysis (aka inference) is |
| 35 // reimplemented on kernel. | 38 // reimplemented on kernel. |
| 36 Expression builtBinary; | 39 Expression builtBinary; |
| 37 Expression builtGetter; | 40 Expression builtGetter; |
| 38 | 41 |
| 39 Accessor(this.offset); | 42 Accessor(this.token); |
| 40 | 43 |
| 41 /// Builds an [Expression] representing a read from the accessor. | 44 /// Builds an [Expression] representing a read from the accessor. |
| 42 Expression buildSimpleRead() { | 45 Expression buildSimpleRead() { |
| 43 return _finish(_makeSimpleRead()); | 46 return _finish(_makeSimpleRead()); |
| 44 } | 47 } |
| 45 | 48 |
| 46 /// Builds an [Expression] representing an assignment with the accessor on | 49 /// Builds an [Expression] representing an assignment with the accessor on |
| 47 /// the LHS and [value] on the RHS. | 50 /// the LHS and [value] on the RHS. |
| 48 /// | 51 /// |
| 49 /// The returned expression evaluates to the assigned value, unless | 52 /// The returned expression evaluates to the assigned value, unless |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 /// [value]. | 141 /// [value]. |
| 139 /// | 142 /// |
| 140 /// At runtime, [value] will be evaluated before throwing an exception. | 143 /// At runtime, [value] will be evaluated before throwing an exception. |
| 141 makeInvalidWrite(Expression value) => wrapInvalid(value); | 144 makeInvalidWrite(Expression value) => wrapInvalid(value); |
| 142 } | 145 } |
| 143 | 146 |
| 144 class VariableAccessor extends Accessor { | 147 class VariableAccessor extends Accessor { |
| 145 VariableDeclaration variable; | 148 VariableDeclaration variable; |
| 146 DartType promotedType; | 149 DartType promotedType; |
| 147 | 150 |
| 148 VariableAccessor(this.variable, this.promotedType, int offset) | 151 VariableAccessor(this.variable, this.promotedType, Token token) |
| 149 : super(offset); | 152 : super(token); |
| 150 | 153 |
| 151 Expression _makeRead() => | 154 Expression _makeRead() => new VariableGet(variable, promotedType) |
| 152 new VariableGet(variable, promotedType)..fileOffset = offset; | 155 ..fileOffset = offsetForToken(token); |
| 153 | 156 |
| 154 Expression _makeWrite(Expression value, bool voidContext) { | 157 Expression _makeWrite(Expression value, bool voidContext) { |
| 155 return variable.isFinal || variable.isConst | 158 return variable.isFinal || variable.isConst |
| 156 ? makeInvalidWrite(value) | 159 ? makeInvalidWrite(value) |
| 157 : new VariableSet(variable, value) | 160 : new VariableSet(variable, value) |
| 158 ..fileOffset = offset; | 161 ..fileOffset = offsetForToken(token); |
| 159 } | 162 } |
| 160 } | 163 } |
| 161 | 164 |
| 162 class PropertyAccessor extends Accessor { | 165 class PropertyAccessor extends Accessor { |
| 163 VariableDeclaration _receiverVariable; | 166 VariableDeclaration _receiverVariable; |
| 164 Expression receiver; | 167 Expression receiver; |
| 165 Name name; | 168 Name name; |
| 166 Member getter, setter; | 169 Member getter, setter; |
| 167 | 170 |
| 168 static Accessor make( | 171 static Accessor make( |
| 169 Expression receiver, Name name, Member getter, Member setter, | 172 Expression receiver, Name name, Member getter, Member setter, |
| 170 {int offset: TreeNode.noOffset}) { | 173 {Token token}) { |
| 171 if (receiver is ThisExpression) { | 174 if (receiver is ThisExpression) { |
| 172 return new ThisPropertyAccessor(name, getter, setter, offset); | 175 return new ThisPropertyAccessor(name, getter, setter, token); |
| 173 } else { | 176 } else { |
| 174 return new PropertyAccessor.internal( | 177 return new PropertyAccessor.internal( |
| 175 receiver, name, getter, setter, offset); | 178 receiver, name, getter, setter, token); |
| 176 } | 179 } |
| 177 } | 180 } |
| 178 | 181 |
| 179 PropertyAccessor.internal( | 182 PropertyAccessor.internal( |
| 180 this.receiver, this.name, this.getter, this.setter, int offset) | 183 this.receiver, this.name, this.getter, this.setter, Token token) |
| 181 : super(offset); | 184 : super(token); |
| 182 | 185 |
| 183 Expression _makeSimpleRead() => | 186 Expression _makeSimpleRead() => new PropertyGet(receiver, name, getter) |
| 184 new PropertyGet(receiver, name, getter)..fileOffset = offset; | 187 ..fileOffset = offsetForToken(token); |
| 185 | 188 |
| 186 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 189 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
| 187 return new PropertySet(receiver, name, value, setter)..fileOffset = offset; | 190 return new PropertySet(receiver, name, value, setter) |
| 191 ..fileOffset = offsetForToken(token); |
| 188 } | 192 } |
| 189 | 193 |
| 190 receiverAccess() { | 194 receiverAccess() { |
| 191 _receiverVariable ??= new VariableDeclaration.forValue(receiver); | 195 _receiverVariable ??= new VariableDeclaration.forValue(receiver); |
| 192 return new VariableGet(_receiverVariable)..fileOffset = offset; | 196 return new VariableGet(_receiverVariable) |
| 197 ..fileOffset = offsetForToken(token); |
| 193 } | 198 } |
| 194 | 199 |
| 195 Expression _makeRead() => builtGetter = | 200 Expression _makeRead() => |
| 196 new PropertyGet(receiverAccess(), name, getter)..fileOffset = offset; | 201 builtGetter = new PropertyGet(receiverAccess(), name, getter) |
| 202 ..fileOffset = offsetForToken(token); |
| 197 | 203 |
| 198 Expression _makeWrite(Expression value, bool voidContext) { | 204 Expression _makeWrite(Expression value, bool voidContext) { |
| 199 return new PropertySet(receiverAccess(), name, value, setter) | 205 return new PropertySet(receiverAccess(), name, value, setter) |
| 200 ..fileOffset = offset; | 206 ..fileOffset = offsetForToken(token); |
| 201 } | 207 } |
| 202 | 208 |
| 203 Expression _finish(Expression body) => makeLet(_receiverVariable, body); | 209 Expression _finish(Expression body) => makeLet(_receiverVariable, body); |
| 204 } | 210 } |
| 205 | 211 |
| 206 /// Special case of [PropertyAccessor] to avoid creating an indirect access to | 212 /// Special case of [PropertyAccessor] to avoid creating an indirect access to |
| 207 /// 'this'. | 213 /// 'this'. |
| 208 class ThisPropertyAccessor extends Accessor { | 214 class ThisPropertyAccessor extends Accessor { |
| 209 Name name; | 215 Name name; |
| 210 Member getter, setter; | 216 Member getter, setter; |
| 211 | 217 |
| 212 ThisPropertyAccessor(this.name, this.getter, this.setter, int offset) | 218 ThisPropertyAccessor(this.name, this.getter, this.setter, Token token) |
| 213 : super(offset); | 219 : super(token); |
| 214 | 220 |
| 215 Expression _makeRead() => builtGetter = | 221 Expression _makeRead() => |
| 216 new PropertyGet(new ThisExpression(), name, getter)..fileOffset = offset; | 222 builtGetter = new PropertyGet(new ThisExpression(), name, getter) |
| 223 ..fileOffset = offsetForToken(token); |
| 217 | 224 |
| 218 Expression _makeWrite(Expression value, bool voidContext) { | 225 Expression _makeWrite(Expression value, bool voidContext) { |
| 219 return new PropertySet(new ThisExpression(), name, value, setter) | 226 return new PropertySet(new ThisExpression(), name, value, setter) |
| 220 ..fileOffset = offset; | 227 ..fileOffset = offsetForToken(token); |
| 221 } | 228 } |
| 222 } | 229 } |
| 223 | 230 |
| 224 class NullAwarePropertyAccessor extends Accessor { | 231 class NullAwarePropertyAccessor extends Accessor { |
| 225 VariableDeclaration receiver; | 232 VariableDeclaration receiver; |
| 226 Name name; | 233 Name name; |
| 227 Member getter, setter; | 234 Member getter, setter; |
| 228 DartType type; | 235 DartType type; |
| 229 | 236 |
| 230 NullAwarePropertyAccessor(Expression receiver, this.name, this.getter, | 237 NullAwarePropertyAccessor(Expression receiver, this.name, this.getter, |
| 231 this.setter, this.type, int offset) | 238 this.setter, this.type, Token token) |
| 232 : this.receiver = makeOrReuseVariable(receiver), | 239 : this.receiver = makeOrReuseVariable(receiver), |
| 233 super(offset); | 240 super(token); |
| 234 | 241 |
| 235 receiverAccess() => new VariableGet(receiver); | 242 receiverAccess() => new VariableGet(receiver); |
| 236 | 243 |
| 237 Expression _makeRead() => | 244 Expression _makeRead() => |
| 238 builtGetter = new PropertyGet(receiverAccess(), name, getter); | 245 builtGetter = new PropertyGet(receiverAccess(), name, getter); |
| 239 | 246 |
| 240 Expression _makeWrite(Expression value, bool voidContext) { | 247 Expression _makeWrite(Expression value, bool voidContext) { |
| 241 return new PropertySet(receiverAccess(), name, value, setter); | 248 return new PropertySet(receiverAccess(), name, value, setter); |
| 242 } | 249 } |
| 243 | 250 |
| 244 Expression _finish(Expression body) => makeLet( | 251 Expression _finish(Expression body) => makeLet( |
| 245 receiver, | 252 receiver, |
| 246 new ConditionalExpression( | 253 new ConditionalExpression( |
| 247 buildIsNull(receiverAccess()), new NullLiteral(), body, type)); | 254 buildIsNull(receiverAccess()), new NullLiteral(), body, type)); |
| 248 } | 255 } |
| 249 | 256 |
| 250 class SuperPropertyAccessor extends Accessor { | 257 class SuperPropertyAccessor extends Accessor { |
| 251 Name name; | 258 Name name; |
| 252 Member getter, setter; | 259 Member getter, setter; |
| 253 | 260 |
| 254 SuperPropertyAccessor(this.name, this.getter, this.setter, int offset) | 261 SuperPropertyAccessor(this.name, this.getter, this.setter, Token token) |
| 255 : super(offset); | 262 : super(token); |
| 256 | 263 |
| 257 Expression _makeRead() { | 264 Expression _makeRead() { |
| 258 if (getter == null) return makeInvalidRead(); | 265 if (getter == null) return makeInvalidRead(); |
| 259 // TODO(ahe): Use [DirectPropertyGet] when possible. | 266 // TODO(ahe): Use [DirectPropertyGet] when possible. |
| 260 return builtGetter = new SuperPropertyGet(name, getter) | 267 return builtGetter = new SuperPropertyGet(name, getter) |
| 261 ..fileOffset = offset; | 268 ..fileOffset = offsetForToken(token); |
| 262 } | 269 } |
| 263 | 270 |
| 264 Expression _makeWrite(Expression value, bool voidContext) { | 271 Expression _makeWrite(Expression value, bool voidContext) { |
| 265 if (setter == null) return makeInvalidWrite(value); | 272 if (setter == null) return makeInvalidWrite(value); |
| 266 // TODO(ahe): Use [DirectPropertySet] when possible. | 273 // TODO(ahe): Use [DirectPropertySet] when possible. |
| 267 return new SuperPropertySet(name, value, setter)..fileOffset = offset; | 274 return new SuperPropertySet(name, value, setter) |
| 275 ..fileOffset = offsetForToken(token); |
| 268 } | 276 } |
| 269 } | 277 } |
| 270 | 278 |
| 271 class IndexAccessor extends Accessor { | 279 class IndexAccessor extends Accessor { |
| 272 Expression receiver; | 280 Expression receiver; |
| 273 Expression index; | 281 Expression index; |
| 274 VariableDeclaration receiverVariable; | 282 VariableDeclaration receiverVariable; |
| 275 VariableDeclaration indexVariable; | 283 VariableDeclaration indexVariable; |
| 276 Procedure getter, setter; | 284 Procedure getter, setter; |
| 277 | 285 |
| 278 static Accessor make( | 286 static Accessor make( |
| 279 Expression receiver, Expression index, Procedure getter, Procedure setter, | 287 Expression receiver, Expression index, Procedure getter, Procedure setter, |
| 280 {int offset: TreeNode.noOffset}) { | 288 {Token token}) { |
| 281 if (receiver is ThisExpression) { | 289 if (receiver is ThisExpression) { |
| 282 return new ThisIndexAccessor(index, getter, setter, offset); | 290 return new ThisIndexAccessor(index, getter, setter, token); |
| 283 } else { | 291 } else { |
| 284 return new IndexAccessor.internal( | 292 return new IndexAccessor.internal(receiver, index, getter, setter, token); |
| 285 receiver, index, getter, setter, offset); | |
| 286 } | 293 } |
| 287 } | 294 } |
| 288 | 295 |
| 289 IndexAccessor.internal( | 296 IndexAccessor.internal( |
| 290 this.receiver, this.index, this.getter, this.setter, int offset) | 297 this.receiver, this.index, this.getter, this.setter, Token token) |
| 291 : super(offset); | 298 : super(token); |
| 292 | 299 |
| 293 Expression _makeSimpleRead() => new MethodInvocation( | 300 Expression _makeSimpleRead() => new MethodInvocation( |
| 294 receiver, indexGetName, new Arguments(<Expression>[index]), getter) | 301 receiver, indexGetName, new Arguments(<Expression>[index]), getter) |
| 295 ..fileOffset = offset; | 302 ..fileOffset = offsetForToken(token); |
| 296 | 303 |
| 297 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 304 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
| 298 if (!voidContext) return _makeWriteAndReturn(value); | 305 if (!voidContext) return _makeWriteAndReturn(value); |
| 299 return new MethodInvocation(receiver, indexSetName, | 306 return new MethodInvocation(receiver, indexSetName, |
| 300 new Arguments(<Expression>[index, value]), setter) | 307 new Arguments(<Expression>[index, value]), setter) |
| 301 ..fileOffset = offset; | 308 ..fileOffset = offsetForToken(token); |
| 302 } | 309 } |
| 303 | 310 |
| 304 receiverAccess() { | 311 receiverAccess() { |
| 305 // We cannot reuse the receiver if it is a variable since it might be | 312 // We cannot reuse the receiver if it is a variable since it might be |
| 306 // reassigned in the index expression. | 313 // reassigned in the index expression. |
| 307 receiverVariable ??= new VariableDeclaration.forValue(receiver); | 314 receiverVariable ??= new VariableDeclaration.forValue(receiver); |
| 308 return new VariableGet(receiverVariable)..fileOffset = offset; | 315 return new VariableGet(receiverVariable) |
| 316 ..fileOffset = offsetForToken(token); |
| 309 } | 317 } |
| 310 | 318 |
| 311 indexAccess() { | 319 indexAccess() { |
| 312 indexVariable ??= new VariableDeclaration.forValue(index); | 320 indexVariable ??= new VariableDeclaration.forValue(index); |
| 313 return new VariableGet(indexVariable)..fileOffset = offset; | 321 return new VariableGet(indexVariable)..fileOffset = offsetForToken(token); |
| 314 } | 322 } |
| 315 | 323 |
| 316 Expression _makeRead() { | 324 Expression _makeRead() { |
| 317 return builtGetter = new MethodInvocation(receiverAccess(), indexGetName, | 325 return builtGetter = new MethodInvocation(receiverAccess(), indexGetName, |
| 318 new Arguments(<Expression>[indexAccess()]), getter) | 326 new Arguments(<Expression>[indexAccess()]), getter) |
| 319 ..fileOffset = offset; | 327 ..fileOffset = offsetForToken(token); |
| 320 } | 328 } |
| 321 | 329 |
| 322 Expression _makeWrite(Expression value, bool voidContext) { | 330 Expression _makeWrite(Expression value, bool voidContext) { |
| 323 if (!voidContext) return _makeWriteAndReturn(value); | 331 if (!voidContext) return _makeWriteAndReturn(value); |
| 324 return new MethodInvocation(receiverAccess(), indexSetName, | 332 return new MethodInvocation(receiverAccess(), indexSetName, |
| 325 new Arguments(<Expression>[indexAccess(), value]), setter) | 333 new Arguments(<Expression>[indexAccess(), value]), setter) |
| 326 ..fileOffset = offset; | 334 ..fileOffset = offsetForToken(token); |
| 327 } | 335 } |
| 328 | 336 |
| 329 // TODO(dmitryas): remove this method after the "[]=" operator of the Context | 337 // TODO(dmitryas): remove this method after the "[]=" operator of the Context |
| 330 // class is made to return a value. | 338 // class is made to return a value. |
| 331 _makeWriteAndReturn(Expression value) { | 339 _makeWriteAndReturn(Expression value) { |
| 332 // The call to []= does not return the value like direct-style assignments | 340 // The call to []= does not return the value like direct-style assignments |
| 333 // do. We need to bind the value in a let. | 341 // do. We need to bind the value in a let. |
| 334 var valueVariable = new VariableDeclaration.forValue(value); | 342 var valueVariable = new VariableDeclaration.forValue(value); |
| 335 var dummy = new VariableDeclaration.forValue(new MethodInvocation( | 343 var dummy = new VariableDeclaration.forValue(new MethodInvocation( |
| 336 receiverAccess(), | 344 receiverAccess(), |
| 337 indexSetName, | 345 indexSetName, |
| 338 new Arguments( | 346 new Arguments( |
| 339 <Expression>[indexAccess(), new VariableGet(valueVariable)]), | 347 <Expression>[indexAccess(), new VariableGet(valueVariable)]), |
| 340 setter) | 348 setter) |
| 341 ..fileOffset = offset); | 349 ..fileOffset = offsetForToken(token)); |
| 342 return makeLet( | 350 return makeLet( |
| 343 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); | 351 valueVariable, makeLet(dummy, new VariableGet(valueVariable))); |
| 344 } | 352 } |
| 345 | 353 |
| 346 Expression _finish(Expression body) { | 354 Expression _finish(Expression body) { |
| 347 return makeLet(receiverVariable, makeLet(indexVariable, body)); | 355 return makeLet(receiverVariable, makeLet(indexVariable, body)); |
| 348 } | 356 } |
| 349 } | 357 } |
| 350 | 358 |
| 351 /// Special case of [IndexAccessor] to avoid creating an indirect access to | 359 /// Special case of [IndexAccessor] to avoid creating an indirect access to |
| 352 /// 'this'. | 360 /// 'this'. |
| 353 class ThisIndexAccessor extends Accessor { | 361 class ThisIndexAccessor extends Accessor { |
| 354 Expression index; | 362 Expression index; |
| 355 VariableDeclaration indexVariable; | 363 VariableDeclaration indexVariable; |
| 356 Procedure getter, setter; | 364 Procedure getter, setter; |
| 357 | 365 |
| 358 ThisIndexAccessor(this.index, this.getter, this.setter, int offset) | 366 ThisIndexAccessor(this.index, this.getter, this.setter, Token token) |
| 359 : super(offset); | 367 : super(token); |
| 360 | 368 |
| 361 Expression _makeSimpleRead() { | 369 Expression _makeSimpleRead() { |
| 362 return new MethodInvocation(new ThisExpression(), indexGetName, | 370 return new MethodInvocation(new ThisExpression(), indexGetName, |
| 363 new Arguments(<Expression>[index]), getter); | 371 new Arguments(<Expression>[index]), getter); |
| 364 } | 372 } |
| 365 | 373 |
| 366 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 374 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
| 367 if (!voidContext) return _makeWriteAndReturn(value); | 375 if (!voidContext) return _makeWriteAndReturn(value); |
| 368 return new MethodInvocation(new ThisExpression(), indexSetName, | 376 return new MethodInvocation(new ThisExpression(), indexSetName, |
| 369 new Arguments(<Expression>[index, value]), setter); | 377 new Arguments(<Expression>[index, value]), setter); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 399 } | 407 } |
| 400 | 408 |
| 401 Expression _finish(Expression body) => makeLet(indexVariable, body); | 409 Expression _finish(Expression body) => makeLet(indexVariable, body); |
| 402 } | 410 } |
| 403 | 411 |
| 404 class SuperIndexAccessor extends Accessor { | 412 class SuperIndexAccessor extends Accessor { |
| 405 Expression index; | 413 Expression index; |
| 406 VariableDeclaration indexVariable; | 414 VariableDeclaration indexVariable; |
| 407 Member getter, setter; | 415 Member getter, setter; |
| 408 | 416 |
| 409 SuperIndexAccessor(this.index, this.getter, this.setter, int offset) | 417 SuperIndexAccessor(this.index, this.getter, this.setter, Token token) |
| 410 : super(offset); | 418 : super(token); |
| 411 | 419 |
| 412 indexAccess() { | 420 indexAccess() { |
| 413 indexVariable ??= new VariableDeclaration.forValue(index); | 421 indexVariable ??= new VariableDeclaration.forValue(index); |
| 414 return new VariableGet(indexVariable); | 422 return new VariableGet(indexVariable); |
| 415 } | 423 } |
| 416 | 424 |
| 417 Expression _makeSimpleRead() => new SuperMethodInvocation( | 425 Expression _makeSimpleRead() => new SuperMethodInvocation( |
| 418 indexGetName, new Arguments(<Expression>[index]), getter); | 426 indexGetName, new Arguments(<Expression>[index]), getter); |
| 419 | 427 |
| 420 Expression _makeSimpleWrite(Expression value, bool voidContext) { | 428 Expression _makeSimpleWrite(Expression value, bool voidContext) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 448 Expression _finish(Expression body) { | 456 Expression _finish(Expression body) { |
| 449 return makeLet(indexVariable, body); | 457 return makeLet(indexVariable, body); |
| 450 } | 458 } |
| 451 } | 459 } |
| 452 | 460 |
| 453 class StaticAccessor extends Accessor { | 461 class StaticAccessor extends Accessor { |
| 454 final BuilderHelper helper; | 462 final BuilderHelper helper; |
| 455 Member readTarget; | 463 Member readTarget; |
| 456 Member writeTarget; | 464 Member writeTarget; |
| 457 | 465 |
| 458 StaticAccessor(this.helper, this.readTarget, this.writeTarget, int offset) | 466 StaticAccessor(this.helper, this.readTarget, this.writeTarget, Token token) |
| 459 : super(offset); | 467 : super(token); |
| 460 | 468 |
| 461 Expression _makeRead() => builtGetter = readTarget == null | 469 Expression _makeRead() => builtGetter = readTarget == null |
| 462 ? makeInvalidRead() | 470 ? makeInvalidRead() |
| 463 : helper.makeStaticGet(readTarget, offset); | 471 : helper.makeStaticGet(readTarget, token); |
| 464 | 472 |
| 465 Expression _makeWrite(Expression value, bool voidContext) { | 473 Expression _makeWrite(Expression value, bool voidContext) { |
| 466 return writeTarget == null | 474 return writeTarget == null |
| 467 ? makeInvalidWrite(value) | 475 ? makeInvalidWrite(value) |
| 468 : new StaticSet(writeTarget, value) | 476 : new StaticSet(writeTarget, value) |
| 469 ..fileOffset = offset; | 477 ..fileOffset = offsetForToken(token); |
| 470 } | 478 } |
| 471 } | 479 } |
| 472 | 480 |
| 473 class ReadOnlyAccessor extends Accessor { | 481 class ReadOnlyAccessor extends Accessor { |
| 474 Expression expression; | 482 Expression expression; |
| 475 VariableDeclaration value; | 483 VariableDeclaration value; |
| 476 | 484 |
| 477 ReadOnlyAccessor(this.expression, int offset) : super(offset); | 485 ReadOnlyAccessor(this.expression, Token token) : super(token); |
| 478 | 486 |
| 479 Expression _makeSimpleRead() => expression; | 487 Expression _makeSimpleRead() => expression; |
| 480 | 488 |
| 481 Expression _makeRead() { | 489 Expression _makeRead() { |
| 482 value ??= new VariableDeclaration.forValue(expression); | 490 value ??= new VariableDeclaration.forValue(expression); |
| 483 return new VariableGet(value); | 491 return new VariableGet(value); |
| 484 } | 492 } |
| 485 | 493 |
| 486 Expression _makeWrite(Expression value, bool voidContext) => | 494 Expression _makeWrite(Expression value, bool voidContext) => |
| 487 makeInvalidWrite(value); | 495 makeInvalidWrite(value); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 511 | 519 |
| 512 VariableDeclaration makeOrReuseVariable(Expression value) { | 520 VariableDeclaration makeOrReuseVariable(Expression value) { |
| 513 // TODO: Devise a way to remember if a variable declaration was reused | 521 // TODO: Devise a way to remember if a variable declaration was reused |
| 514 // or is fresh (hence needs a let binding). | 522 // or is fresh (hence needs a let binding). |
| 515 return new VariableDeclaration.forValue(value); | 523 return new VariableDeclaration.forValue(value); |
| 516 } | 524 } |
| 517 | 525 |
| 518 Expression wrapInvalid(Expression e) { | 526 Expression wrapInvalid(Expression e) { |
| 519 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); | 527 return new Let(new VariableDeclaration.forValue(e), new InvalidExpression()); |
| 520 } | 528 } |
| OLD | NEW |