| OLD | NEW |
| (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 library serialization.summarize_const_expr; |
| 6 |
| 7 import 'package:analyzer/dart/ast/ast.dart'; |
| 8 import 'package:analyzer/dart/ast/token.dart'; |
| 9 import 'package:analyzer/dart/element/type.dart' show DartType; |
| 10 import 'package:analyzer/src/summary/format.dart'; |
| 11 import 'package:analyzer/src/summary/idl.dart'; |
| 12 |
| 13 /** |
| 14 * Serialize the given constructor initializer [node]. |
| 15 */ |
| 16 UnlinkedConstructorInitializer serializeConstructorInitializer( |
| 17 ConstructorInitializer node, |
| 18 UnlinkedConstBuilder serializeConstExpr(Expression expr)) { |
| 19 if (node is ConstructorFieldInitializer) { |
| 20 return new UnlinkedConstructorInitializerBuilder( |
| 21 kind: UnlinkedConstructorInitializerKind.field, |
| 22 name: node.fieldName.name, |
| 23 expression: serializeConstExpr(node.expression)); |
| 24 } |
| 25 |
| 26 List<UnlinkedConstBuilder> arguments = <UnlinkedConstBuilder>[]; |
| 27 List<String> argumentNames = <String>[]; |
| 28 void serializeArguments(List<Expression> args) { |
| 29 for (Expression arg in args) { |
| 30 if (arg is NamedExpression) { |
| 31 NamedExpression namedExpression = arg; |
| 32 argumentNames.add(namedExpression.name.label.name); |
| 33 arg = namedExpression.expression; |
| 34 } |
| 35 arguments.add(serializeConstExpr(arg)); |
| 36 } |
| 37 } |
| 38 |
| 39 if (node is RedirectingConstructorInvocation) { |
| 40 serializeArguments(node.argumentList.arguments); |
| 41 return new UnlinkedConstructorInitializerBuilder( |
| 42 kind: UnlinkedConstructorInitializerKind.thisInvocation, |
| 43 name: node?.constructorName?.name, |
| 44 arguments: arguments, |
| 45 argumentNames: argumentNames); |
| 46 } |
| 47 if (node is SuperConstructorInvocation) { |
| 48 serializeArguments(node.argumentList.arguments); |
| 49 return new UnlinkedConstructorInitializerBuilder( |
| 50 kind: UnlinkedConstructorInitializerKind.superInvocation, |
| 51 name: node?.constructorName?.name, |
| 52 arguments: arguments, |
| 53 argumentNames: argumentNames); |
| 54 } |
| 55 throw new StateError('Unexpected initializer type ${node.runtimeType}'); |
| 56 } |
| 57 |
| 58 /** |
| 59 * Instances of this class keep track of intermediate state during |
| 60 * serialization of a single constant [Expression]. |
| 61 */ |
| 62 abstract class AbstractConstExprSerializer { |
| 63 /** |
| 64 * See [UnlinkedConstBuilder.isValidConst]. |
| 65 */ |
| 66 bool isValidConst = true; |
| 67 |
| 68 /** |
| 69 * See [UnlinkedConstBuilder.nmae]. |
| 70 */ |
| 71 String name = null; |
| 72 |
| 73 /** |
| 74 * See [UnlinkedConstBuilder.operations]. |
| 75 */ |
| 76 final List<UnlinkedConstOperation> operations = <UnlinkedConstOperation>[]; |
| 77 |
| 78 /** |
| 79 * See [UnlinkedConstBuilder.assignmentOperators]. |
| 80 */ |
| 81 final List<UnlinkedExprAssignOperator> assignmentOperators = |
| 82 <UnlinkedExprAssignOperator>[]; |
| 83 |
| 84 /** |
| 85 * See [UnlinkedConstBuilder.ints]. |
| 86 */ |
| 87 final List<int> ints = <int>[]; |
| 88 |
| 89 /** |
| 90 * See [UnlinkedConstBuilder.doubles]. |
| 91 */ |
| 92 final List<double> doubles = <double>[]; |
| 93 |
| 94 /** |
| 95 * See [UnlinkedConstBuilder.strings]. |
| 96 */ |
| 97 final List<String> strings = <String>[]; |
| 98 |
| 99 /** |
| 100 * See [UnlinkedConstBuilder.references]. |
| 101 */ |
| 102 final List<EntityRefBuilder> references = <EntityRefBuilder>[]; |
| 103 |
| 104 /** |
| 105 * Return `true` if the given [name] is a parameter reference. |
| 106 */ |
| 107 bool isParameterName(String name); |
| 108 |
| 109 /** |
| 110 * Serialize the given [expr] expression into this serializer state. |
| 111 */ |
| 112 void serialize(Expression expr) { |
| 113 try { |
| 114 if (expr is NamedExpression) { |
| 115 NamedExpression namedExpression = expr; |
| 116 name = namedExpression.name.label.name; |
| 117 expr = namedExpression.expression; |
| 118 } |
| 119 _serialize(expr); |
| 120 } on StateError { |
| 121 isValidConst = false; |
| 122 } |
| 123 } |
| 124 |
| 125 /** |
| 126 * Serialize the given [annotation] into this serializer state. |
| 127 */ |
| 128 void serializeAnnotation(Annotation annotation); |
| 129 |
| 130 /** |
| 131 * Return [EntityRefBuilder] that corresponds to the constructor having name |
| 132 * [name] in the class identified by [typeName]. It is expected that [type] |
| 133 * corresponds to the given [typeName] and [typeArguments]. The parameter |
| 134 * [type] might be `null` if the type is not resolved. |
| 135 */ |
| 136 EntityRefBuilder serializeConstructorRef(DartType type, Identifier typeName, |
| 137 TypeArgumentList typeArguments, SimpleIdentifier name); |
| 138 |
| 139 /** |
| 140 * Return a pair of ints showing how the given [functionExpression] is nested |
| 141 * within the constant currently being serialized. The first int indicates |
| 142 * how many levels of function nesting must be popped in order to reach the |
| 143 * parent of the [functionExpression]. The second int is the index of the |
| 144 * [functionExpression] within its parent element. |
| 145 * |
| 146 * If the constant being summarized is in a context where local function |
| 147 * references are not allowed, return `null`. |
| 148 */ |
| 149 List<int> serializeFunctionExpression(FunctionExpression functionExpression); |
| 150 |
| 151 /** |
| 152 * Return [EntityRefBuilder] that corresponds to the given [identifier]. |
| 153 */ |
| 154 EntityRefBuilder serializeIdentifier(Identifier identifier); |
| 155 |
| 156 /** |
| 157 * Return [EntityRefBuilder] that corresponds to the given [expr], which |
| 158 * must be a sequence of identifiers. |
| 159 */ |
| 160 EntityRefBuilder serializeIdentifierSequence(Expression expr); |
| 161 |
| 162 void serializeInstanceCreation( |
| 163 EntityRefBuilder constructor, ArgumentList argumentList) { |
| 164 _serializeArguments(argumentList); |
| 165 references.add(constructor); |
| 166 operations.add(UnlinkedConstOperation.invokeConstructor); |
| 167 } |
| 168 |
| 169 /** |
| 170 * Return [EntityRefBuilder] that corresponds to the [type] with the given |
| 171 * [name] and [arguments]. It is expected that [type] corresponds to the |
| 172 * given [name] and [arguments]. The parameter [type] might be `null` if the |
| 173 * type is not resolved. |
| 174 */ |
| 175 EntityRefBuilder serializeType( |
| 176 DartType type, Identifier name, TypeArgumentList arguments); |
| 177 |
| 178 /** |
| 179 * Return [EntityRefBuilder] that corresponds to the given [type]. |
| 180 */ |
| 181 EntityRefBuilder serializeTypeName(TypeName type) { |
| 182 return serializeType(type?.type, type?.name, type?.typeArguments); |
| 183 } |
| 184 |
| 185 /** |
| 186 * Return the [UnlinkedConstBuilder] that corresponds to the state of this |
| 187 * serializer. |
| 188 */ |
| 189 UnlinkedConstBuilder toBuilder() { |
| 190 return new UnlinkedConstBuilder( |
| 191 isValidConst: isValidConst, |
| 192 operations: operations, |
| 193 assignmentOperators: assignmentOperators, |
| 194 ints: ints, |
| 195 doubles: doubles, |
| 196 strings: strings, |
| 197 references: references); |
| 198 } |
| 199 |
| 200 /** |
| 201 * Return `true` if the given [expr] is a sequence of identifiers. |
| 202 */ |
| 203 bool _isIdentifierSequence(Expression expr) { |
| 204 while (expr != null) { |
| 205 if (expr is SimpleIdentifier) { |
| 206 AstNode parent = expr.parent; |
| 207 if (parent is MethodInvocation && parent.methodName == expr) { |
| 208 if (parent.isCascaded) { |
| 209 return false; |
| 210 } |
| 211 return parent.target == null || _isIdentifierSequence(parent.target); |
| 212 } |
| 213 if (isParameterName(expr.name)) { |
| 214 return false; |
| 215 } |
| 216 return true; |
| 217 } else if (expr is PrefixedIdentifier) { |
| 218 expr = (expr as PrefixedIdentifier).prefix; |
| 219 } else if (expr is PropertyAccess) { |
| 220 expr = (expr as PropertyAccess).target; |
| 221 } else { |
| 222 return false; |
| 223 } |
| 224 } |
| 225 return false; |
| 226 } |
| 227 |
| 228 /** |
| 229 * Push the operation for the given assignable [expr]. |
| 230 */ |
| 231 void _pushAssignable(Expression expr) { |
| 232 if (_isIdentifierSequence(expr)) { |
| 233 EntityRefBuilder ref = serializeIdentifierSequence(expr); |
| 234 references.add(ref); |
| 235 operations.add(UnlinkedConstOperation.assignToRef); |
| 236 } else if (expr is PropertyAccess) { |
| 237 if (!expr.isCascaded) { |
| 238 _serialize(expr.target); |
| 239 } |
| 240 strings.add(expr.propertyName.name); |
| 241 operations.add(UnlinkedConstOperation.assignToProperty); |
| 242 } else if (expr is IndexExpression) { |
| 243 if (!expr.isCascaded) { |
| 244 _serialize(expr.target); |
| 245 } |
| 246 _serialize(expr.index); |
| 247 operations.add(UnlinkedConstOperation.assignToIndex); |
| 248 } else if (expr is PrefixedIdentifier) { |
| 249 strings.add(expr.prefix.name); |
| 250 operations.add(UnlinkedConstOperation.pushParameter); |
| 251 strings.add(expr.identifier.name); |
| 252 operations.add(UnlinkedConstOperation.assignToProperty); |
| 253 } else { |
| 254 throw new StateError('Unsupported assignable: $expr'); |
| 255 } |
| 256 } |
| 257 |
| 258 void _pushInt(int value) { |
| 259 assert(value >= 0); |
| 260 if (value >= (1 << 32)) { |
| 261 int numOfComponents = 0; |
| 262 ints.add(numOfComponents); |
| 263 void pushComponents(int value) { |
| 264 if (value >= (1 << 32)) { |
| 265 pushComponents(value >> 32); |
| 266 } |
| 267 numOfComponents++; |
| 268 ints.add(value & 0xFFFFFFFF); |
| 269 } |
| 270 pushComponents(value); |
| 271 ints[ints.length - 1 - numOfComponents] = numOfComponents; |
| 272 operations.add(UnlinkedConstOperation.pushLongInt); |
| 273 } else { |
| 274 operations.add(UnlinkedConstOperation.pushInt); |
| 275 ints.add(value); |
| 276 } |
| 277 } |
| 278 |
| 279 /** |
| 280 * Serialize the given [expr] expression into this serializer state. |
| 281 */ |
| 282 void _serialize(Expression expr) { |
| 283 if (expr is IntegerLiteral) { |
| 284 _pushInt(expr.value); |
| 285 } else if (expr is DoubleLiteral) { |
| 286 operations.add(UnlinkedConstOperation.pushDouble); |
| 287 doubles.add(expr.value); |
| 288 } else if (expr is BooleanLiteral) { |
| 289 if (expr.value) { |
| 290 operations.add(UnlinkedConstOperation.pushTrue); |
| 291 } else { |
| 292 operations.add(UnlinkedConstOperation.pushFalse); |
| 293 } |
| 294 } else if (expr is StringLiteral) { |
| 295 _serializeString(expr); |
| 296 } else if (expr is SymbolLiteral) { |
| 297 strings.add(expr.components.map((token) => token.lexeme).join('.')); |
| 298 operations.add(UnlinkedConstOperation.makeSymbol); |
| 299 } else if (expr is NullLiteral) { |
| 300 operations.add(UnlinkedConstOperation.pushNull); |
| 301 } else if (expr is Identifier) { |
| 302 if (expr is SimpleIdentifier && isParameterName(expr.name)) { |
| 303 strings.add(expr.name); |
| 304 operations.add(UnlinkedConstOperation.pushParameter); |
| 305 } else if (expr is PrefixedIdentifier && |
| 306 isParameterName(expr.prefix.name)) { |
| 307 strings.add(expr.prefix.name); |
| 308 operations.add(UnlinkedConstOperation.pushParameter); |
| 309 strings.add(expr.identifier.name); |
| 310 operations.add(UnlinkedConstOperation.extractProperty); |
| 311 } else { |
| 312 references.add(serializeIdentifier(expr)); |
| 313 operations.add(UnlinkedConstOperation.pushReference); |
| 314 } |
| 315 } else if (expr is InstanceCreationExpression) { |
| 316 if (!expr.isConst) { |
| 317 isValidConst = false; |
| 318 } |
| 319 TypeName typeName = expr.constructorName.type; |
| 320 serializeInstanceCreation( |
| 321 serializeConstructorRef(typeName.type, typeName.name, |
| 322 typeName.typeArguments, expr.constructorName.name), |
| 323 expr.argumentList); |
| 324 } else if (expr is ListLiteral) { |
| 325 _serializeListLiteral(expr); |
| 326 } else if (expr is MapLiteral) { |
| 327 _serializeMapLiteral(expr); |
| 328 } else if (expr is MethodInvocation) { |
| 329 _serializeMethodInvocation(expr); |
| 330 } else if (expr is BinaryExpression) { |
| 331 _serializeBinaryExpression(expr); |
| 332 } else if (expr is ConditionalExpression) { |
| 333 _serialize(expr.condition); |
| 334 _serialize(expr.thenExpression); |
| 335 _serialize(expr.elseExpression); |
| 336 operations.add(UnlinkedConstOperation.conditional); |
| 337 } else if (expr is PrefixExpression) { |
| 338 _serializePrefixExpression(expr); |
| 339 } else if (expr is PostfixExpression) { |
| 340 _serializePostfixExpression(expr); |
| 341 } else if (expr is PropertyAccess) { |
| 342 _serializePropertyAccess(expr); |
| 343 } else if (expr is ParenthesizedExpression) { |
| 344 _serialize(expr.expression); |
| 345 } else if (expr is IndexExpression) { |
| 346 isValidConst = false; |
| 347 _serialize(expr.target); |
| 348 _serialize(expr.index); |
| 349 operations.add(UnlinkedConstOperation.extractIndex); |
| 350 } else if (expr is AssignmentExpression) { |
| 351 _serializeAssignment(expr); |
| 352 } else if (expr is CascadeExpression) { |
| 353 _serializeCascadeExpression(expr); |
| 354 } else if (expr is FunctionExpression) { |
| 355 isValidConst = false; |
| 356 List<int> indices = serializeFunctionExpression(expr); |
| 357 if (indices != null) { |
| 358 ints.addAll(serializeFunctionExpression(expr)); |
| 359 operations.add(UnlinkedConstOperation.pushLocalFunctionReference); |
| 360 } else { |
| 361 // Invalid expression; just push null. |
| 362 operations.add(UnlinkedConstOperation.pushNull); |
| 363 } |
| 364 } else if (expr is FunctionExpressionInvocation) { |
| 365 isValidConst = false; |
| 366 // TODO(scheglov) implement |
| 367 operations.add(UnlinkedConstOperation.pushNull); |
| 368 } else if (expr is AsExpression) { |
| 369 isValidConst = false; |
| 370 _serialize(expr.expression); |
| 371 references.add(serializeTypeName(expr.type)); |
| 372 operations.add(UnlinkedConstOperation.typeCast); |
| 373 } else if (expr is IsExpression) { |
| 374 isValidConst = false; |
| 375 _serialize(expr.expression); |
| 376 references.add(serializeTypeName(expr.type)); |
| 377 operations.add(UnlinkedConstOperation.typeCheck); |
| 378 } else if (expr is ThrowExpression) { |
| 379 isValidConst = false; |
| 380 _serialize(expr.expression); |
| 381 operations.add(UnlinkedConstOperation.throwException); |
| 382 } else { |
| 383 throw new StateError('Unknown expression type: $expr'); |
| 384 } |
| 385 } |
| 386 |
| 387 void _serializeArguments(ArgumentList argumentList) { |
| 388 List<Expression> arguments = argumentList.arguments; |
| 389 // Serialize the arguments. |
| 390 List<String> argumentNames = <String>[]; |
| 391 arguments.forEach((arg) { |
| 392 if (arg is NamedExpression) { |
| 393 argumentNames.add(arg.name.label.name); |
| 394 _serialize(arg.expression); |
| 395 } else { |
| 396 _serialize(arg); |
| 397 } |
| 398 }); |
| 399 // Add numbers of named and positional arguments, and the op-code. |
| 400 ints.add(argumentNames.length); |
| 401 strings.addAll(argumentNames); |
| 402 ints.add(arguments.length - argumentNames.length); |
| 403 } |
| 404 |
| 405 void _serializeAssignment(AssignmentExpression expr) { |
| 406 isValidConst = false; |
| 407 // Push the value. |
| 408 _serialize(expr.rightHandSide); |
| 409 // Push the assignment operator. |
| 410 TokenType operator = expr.operator.type; |
| 411 UnlinkedExprAssignOperator assignmentOperator; |
| 412 if (operator == TokenType.EQ) { |
| 413 assignmentOperator = UnlinkedExprAssignOperator.assign; |
| 414 } else if (operator == TokenType.QUESTION_QUESTION_EQ) { |
| 415 assignmentOperator = UnlinkedExprAssignOperator.ifNull; |
| 416 } else if (operator == TokenType.STAR_EQ) { |
| 417 assignmentOperator = UnlinkedExprAssignOperator.multiply; |
| 418 } else if (operator == TokenType.SLASH_EQ) { |
| 419 assignmentOperator = UnlinkedExprAssignOperator.divide; |
| 420 } else if (operator == TokenType.TILDE_SLASH_EQ) { |
| 421 assignmentOperator = UnlinkedExprAssignOperator.floorDivide; |
| 422 } else if (operator == TokenType.PERCENT_EQ) { |
| 423 assignmentOperator = UnlinkedExprAssignOperator.modulo; |
| 424 } else if (operator == TokenType.PLUS_EQ) { |
| 425 assignmentOperator = UnlinkedExprAssignOperator.plus; |
| 426 } else if (operator == TokenType.MINUS_EQ) { |
| 427 assignmentOperator = UnlinkedExprAssignOperator.minus; |
| 428 } else if (operator == TokenType.LT_LT_EQ) { |
| 429 assignmentOperator = UnlinkedExprAssignOperator.shiftLeft; |
| 430 } else if (operator == TokenType.GT_GT_EQ) { |
| 431 assignmentOperator = UnlinkedExprAssignOperator.shiftRight; |
| 432 } else if (operator == TokenType.AMPERSAND_EQ) { |
| 433 assignmentOperator = UnlinkedExprAssignOperator.bitAnd; |
| 434 } else if (operator == TokenType.CARET_EQ) { |
| 435 assignmentOperator = UnlinkedExprAssignOperator.bitXor; |
| 436 } else if (operator == TokenType.BAR_EQ) { |
| 437 assignmentOperator = UnlinkedExprAssignOperator.bitOr; |
| 438 } else { |
| 439 throw new StateError('Unknown assignment operator: $operator'); |
| 440 } |
| 441 assignmentOperators.add(assignmentOperator); |
| 442 // Push the assignment to the LHS. |
| 443 _pushAssignable(expr.leftHandSide); |
| 444 } |
| 445 |
| 446 void _serializeBinaryExpression(BinaryExpression expr) { |
| 447 _serialize(expr.leftOperand); |
| 448 _serialize(expr.rightOperand); |
| 449 TokenType operator = expr.operator.type; |
| 450 if (operator == TokenType.EQ_EQ) { |
| 451 operations.add(UnlinkedConstOperation.equal); |
| 452 } else if (operator == TokenType.BANG_EQ) { |
| 453 operations.add(UnlinkedConstOperation.notEqual); |
| 454 } else if (operator == TokenType.AMPERSAND_AMPERSAND) { |
| 455 operations.add(UnlinkedConstOperation.and); |
| 456 } else if (operator == TokenType.BAR_BAR) { |
| 457 operations.add(UnlinkedConstOperation.or); |
| 458 } else if (operator == TokenType.CARET) { |
| 459 operations.add(UnlinkedConstOperation.bitXor); |
| 460 } else if (operator == TokenType.AMPERSAND) { |
| 461 operations.add(UnlinkedConstOperation.bitAnd); |
| 462 } else if (operator == TokenType.BAR) { |
| 463 operations.add(UnlinkedConstOperation.bitOr); |
| 464 } else if (operator == TokenType.GT_GT) { |
| 465 operations.add(UnlinkedConstOperation.bitShiftRight); |
| 466 } else if (operator == TokenType.LT_LT) { |
| 467 operations.add(UnlinkedConstOperation.bitShiftLeft); |
| 468 } else if (operator == TokenType.PLUS) { |
| 469 operations.add(UnlinkedConstOperation.add); |
| 470 } else if (operator == TokenType.MINUS) { |
| 471 operations.add(UnlinkedConstOperation.subtract); |
| 472 } else if (operator == TokenType.STAR) { |
| 473 operations.add(UnlinkedConstOperation.multiply); |
| 474 } else if (operator == TokenType.SLASH) { |
| 475 operations.add(UnlinkedConstOperation.divide); |
| 476 } else if (operator == TokenType.TILDE_SLASH) { |
| 477 operations.add(UnlinkedConstOperation.floorDivide); |
| 478 } else if (operator == TokenType.GT) { |
| 479 operations.add(UnlinkedConstOperation.greater); |
| 480 } else if (operator == TokenType.LT) { |
| 481 operations.add(UnlinkedConstOperation.less); |
| 482 } else if (operator == TokenType.GT_EQ) { |
| 483 operations.add(UnlinkedConstOperation.greaterEqual); |
| 484 } else if (operator == TokenType.LT_EQ) { |
| 485 operations.add(UnlinkedConstOperation.lessEqual); |
| 486 } else if (operator == TokenType.PERCENT) { |
| 487 operations.add(UnlinkedConstOperation.modulo); |
| 488 } else { |
| 489 throw new StateError('Unknown operator: $operator'); |
| 490 } |
| 491 } |
| 492 |
| 493 void _serializeCascadeExpression(CascadeExpression expr) { |
| 494 _serialize(expr.target); |
| 495 for (Expression section in expr.cascadeSections) { |
| 496 operations.add(UnlinkedConstOperation.cascadeSectionBegin); |
| 497 _serialize(section); |
| 498 operations.add(UnlinkedConstOperation.cascadeSectionEnd); |
| 499 } |
| 500 } |
| 501 |
| 502 void _serializeListLiteral(ListLiteral expr) { |
| 503 List<Expression> elements = expr.elements; |
| 504 elements.forEach(_serialize); |
| 505 ints.add(elements.length); |
| 506 if (expr.typeArguments != null && |
| 507 expr.typeArguments.arguments.length == 1) { |
| 508 references.add(serializeTypeName(expr.typeArguments.arguments[0])); |
| 509 operations.add(UnlinkedConstOperation.makeTypedList); |
| 510 } else { |
| 511 operations.add(UnlinkedConstOperation.makeUntypedList); |
| 512 } |
| 513 } |
| 514 |
| 515 void _serializeMapLiteral(MapLiteral expr) { |
| 516 for (MapLiteralEntry entry in expr.entries) { |
| 517 _serialize(entry.key); |
| 518 _serialize(entry.value); |
| 519 } |
| 520 ints.add(expr.entries.length); |
| 521 if (expr.typeArguments != null && |
| 522 expr.typeArguments.arguments.length == 2) { |
| 523 references.add(serializeTypeName(expr.typeArguments.arguments[0])); |
| 524 references.add(serializeTypeName(expr.typeArguments.arguments[1])); |
| 525 operations.add(UnlinkedConstOperation.makeTypedMap); |
| 526 } else { |
| 527 operations.add(UnlinkedConstOperation.makeUntypedMap); |
| 528 } |
| 529 } |
| 530 |
| 531 void _serializeMethodInvocation(MethodInvocation invocation) { |
| 532 if (invocation.target != null || |
| 533 invocation.methodName.name != 'identical') { |
| 534 isValidConst = false; |
| 535 } |
| 536 Expression target = invocation.target; |
| 537 SimpleIdentifier methodName = invocation.methodName; |
| 538 ArgumentList argumentList = invocation.argumentList; |
| 539 if (_isIdentifierSequence(methodName)) { |
| 540 EntityRefBuilder ref = serializeIdentifierSequence(methodName); |
| 541 _serializeArguments(argumentList); |
| 542 references.add(ref); |
| 543 _serializeTypeArguments(invocation.typeArguments); |
| 544 operations.add(UnlinkedConstOperation.invokeMethodRef); |
| 545 } else { |
| 546 if (!invocation.isCascaded) { |
| 547 _serialize(target); |
| 548 } |
| 549 _serializeArguments(argumentList); |
| 550 strings.add(methodName.name); |
| 551 _serializeTypeArguments(invocation.typeArguments); |
| 552 operations.add(UnlinkedConstOperation.invokeMethod); |
| 553 } |
| 554 } |
| 555 |
| 556 void _serializePostfixExpression(PostfixExpression expr) { |
| 557 TokenType operator = expr.operator.type; |
| 558 Expression operand = expr.operand; |
| 559 if (operator == TokenType.PLUS_PLUS) { |
| 560 _serializePrefixPostfixIncDec( |
| 561 operand, UnlinkedExprAssignOperator.postfixIncrement); |
| 562 } else if (operator == TokenType.MINUS_MINUS) { |
| 563 _serializePrefixPostfixIncDec( |
| 564 operand, UnlinkedExprAssignOperator.postfixDecrement); |
| 565 } else { |
| 566 throw new StateError('Unknown operator: $operator'); |
| 567 } |
| 568 } |
| 569 |
| 570 void _serializePrefixExpression(PrefixExpression expr) { |
| 571 TokenType operator = expr.operator.type; |
| 572 Expression operand = expr.operand; |
| 573 if (operator == TokenType.BANG) { |
| 574 _serialize(operand); |
| 575 operations.add(UnlinkedConstOperation.not); |
| 576 } else if (operator == TokenType.MINUS) { |
| 577 _serialize(operand); |
| 578 operations.add(UnlinkedConstOperation.negate); |
| 579 } else if (operator == TokenType.TILDE) { |
| 580 _serialize(operand); |
| 581 operations.add(UnlinkedConstOperation.complement); |
| 582 } else if (operator == TokenType.PLUS_PLUS) { |
| 583 _serializePrefixPostfixIncDec( |
| 584 operand, UnlinkedExprAssignOperator.prefixIncrement); |
| 585 } else if (operator == TokenType.MINUS_MINUS) { |
| 586 _serializePrefixPostfixIncDec( |
| 587 operand, UnlinkedExprAssignOperator.prefixDecrement); |
| 588 } else { |
| 589 throw new StateError('Unknown operator: $operator'); |
| 590 } |
| 591 } |
| 592 |
| 593 void _serializePrefixPostfixIncDec( |
| 594 Expression operand, UnlinkedExprAssignOperator operator) { |
| 595 isValidConst = false; |
| 596 assignmentOperators.add(operator); |
| 597 _pushAssignable(operand); |
| 598 } |
| 599 |
| 600 void _serializePropertyAccess(PropertyAccess expr) { |
| 601 if (_isIdentifierSequence(expr)) { |
| 602 EntityRefBuilder ref = serializeIdentifierSequence(expr); |
| 603 references.add(ref); |
| 604 operations.add(UnlinkedConstOperation.pushReference); |
| 605 } else { |
| 606 _serialize(expr.target); |
| 607 strings.add(expr.propertyName.name); |
| 608 operations.add(UnlinkedConstOperation.extractProperty); |
| 609 } |
| 610 } |
| 611 |
| 612 void _serializeString(StringLiteral expr) { |
| 613 if (expr is AdjacentStrings) { |
| 614 if (expr.strings.every((string) => string is SimpleStringLiteral)) { |
| 615 operations.add(UnlinkedConstOperation.pushString); |
| 616 strings.add(expr.stringValue); |
| 617 } else { |
| 618 expr.strings.forEach(_serializeString); |
| 619 operations.add(UnlinkedConstOperation.concatenate); |
| 620 ints.add(expr.strings.length); |
| 621 } |
| 622 } else if (expr is SimpleStringLiteral) { |
| 623 operations.add(UnlinkedConstOperation.pushString); |
| 624 strings.add(expr.value); |
| 625 } else { |
| 626 StringInterpolation interpolation = expr as StringInterpolation; |
| 627 for (InterpolationElement element in interpolation.elements) { |
| 628 if (element is InterpolationString) { |
| 629 operations.add(UnlinkedConstOperation.pushString); |
| 630 strings.add(element.value); |
| 631 } else { |
| 632 _serialize((element as InterpolationExpression).expression); |
| 633 } |
| 634 } |
| 635 operations.add(UnlinkedConstOperation.concatenate); |
| 636 ints.add(interpolation.elements.length); |
| 637 } |
| 638 } |
| 639 |
| 640 void _serializeTypeArguments(TypeArgumentList typeArguments) { |
| 641 if (typeArguments == null) { |
| 642 ints.add(0); |
| 643 } else { |
| 644 ints.add(typeArguments.arguments.length); |
| 645 for (TypeName typeName in typeArguments.arguments) { |
| 646 references.add(serializeTypeName(typeName)); |
| 647 } |
| 648 } |
| 649 } |
| 650 } |
| OLD | NEW |