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