| 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 library serialization.summarize_const_expr; | 5 library serialization.summarize_const_expr; |
| 6 | 6 |
| 7 import 'package:analyzer/src/generated/ast.dart'; | 7 import 'package:analyzer/src/generated/ast.dart'; |
| 8 import 'package:analyzer/src/generated/scanner.dart'; | 8 import 'package:analyzer/src/generated/scanner.dart'; |
| 9 import 'package:analyzer/src/summary/format.dart'; | 9 import 'package:analyzer/src/summary/format.dart'; |
| 10 import 'package:analyzer/src/summary/idl.dart'; | 10 import 'package:analyzer/src/summary/idl.dart'; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 * See [UnlinkedConstBuilder.strings]. | 33 * See [UnlinkedConstBuilder.strings]. |
| 34 */ | 34 */ |
| 35 final List<String> strings = <String>[]; | 35 final List<String> strings = <String>[]; |
| 36 | 36 |
| 37 /** | 37 /** |
| 38 * See [UnlinkedConstBuilder.references]. | 38 * See [UnlinkedConstBuilder.references]. |
| 39 */ | 39 */ |
| 40 final List<EntityRefBuilder> references = <EntityRefBuilder>[]; | 40 final List<EntityRefBuilder> references = <EntityRefBuilder>[]; |
| 41 | 41 |
| 42 /** | 42 /** |
| 43 * Return the [UnlinkedConstBuilder] that corresponds to the given [expr]. |
| 44 */ |
| 45 UnlinkedConstBuilder serialize(Expression expr) { |
| 46 try { |
| 47 _serialize(expr); |
| 48 return new UnlinkedConstBuilder( |
| 49 isValid: true, |
| 50 operations: operations, |
| 51 ints: ints, |
| 52 doubles: doubles, |
| 53 strings: strings, |
| 54 references: references); |
| 55 } on StateError { |
| 56 return new UnlinkedConstBuilder(isValid: false); |
| 57 } |
| 58 } |
| 59 |
| 60 /** |
| 61 * Return [EntityRefBuilder] that corresponds to the given [constructor]. |
| 62 */ |
| 63 EntityRefBuilder serializeConstructorName(ConstructorName constructor); |
| 64 |
| 65 /** |
| 66 * Return [EntityRefBuilder] that corresponds to the given [identifier]. |
| 67 */ |
| 68 EntityRefBuilder serializeIdentifier(Identifier identifier); |
| 69 |
| 70 /** |
| 71 * Return [EntityRefBuilder] that corresponds to the given [access]. |
| 72 */ |
| 73 EntityRefBuilder serializePropertyAccess(PropertyAccess access); |
| 74 |
| 75 /** |
| 76 * Return [EntityRefBuilder] that corresponds to the given [type]. |
| 77 */ |
| 78 EntityRefBuilder serializeType(TypeName type); |
| 79 |
| 80 void _pushInt(int value) { |
| 81 assert(value >= 0); |
| 82 if (value >= (1 << 32)) { |
| 83 int numOfComponents = 0; |
| 84 ints.add(numOfComponents); |
| 85 void pushComponents(int value) { |
| 86 if (value >= (1 << 32)) { |
| 87 pushComponents(value >> 32); |
| 88 } |
| 89 numOfComponents++; |
| 90 ints.add(value & 0xFFFFFFFF); |
| 91 } |
| 92 pushComponents(value); |
| 93 ints[ints.length - 1 - numOfComponents] = numOfComponents; |
| 94 operations.add(UnlinkedConstOperation.pushLongInt); |
| 95 } else { |
| 96 operations.add(UnlinkedConstOperation.pushInt); |
| 97 ints.add(value); |
| 98 } |
| 99 } |
| 100 |
| 101 /** |
| 43 * Serialize the given [expr] expression into this serializer state. | 102 * Serialize the given [expr] expression into this serializer state. |
| 44 */ | 103 */ |
| 45 void serialize(Expression expr) { | 104 void _serialize(Expression expr) { |
| 46 if (expr is IntegerLiteral) { | 105 if (expr is IntegerLiteral) { |
| 47 _pushInt(expr.value); | 106 _pushInt(expr.value); |
| 48 } else if (expr is DoubleLiteral) { | 107 } else if (expr is DoubleLiteral) { |
| 49 operations.add(UnlinkedConstOperation.pushDouble); | 108 operations.add(UnlinkedConstOperation.pushDouble); |
| 50 doubles.add(expr.value); | 109 doubles.add(expr.value); |
| 51 } else if (expr is BooleanLiteral) { | 110 } else if (expr is BooleanLiteral) { |
| 52 if (expr.value) { | 111 if (expr.value) { |
| 53 operations.add(UnlinkedConstOperation.pushTrue); | 112 operations.add(UnlinkedConstOperation.pushTrue); |
| 54 } else { | 113 } else { |
| 55 operations.add(UnlinkedConstOperation.pushFalse); | 114 operations.add(UnlinkedConstOperation.pushFalse); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 66 operations.add(UnlinkedConstOperation.pushReference); | 125 operations.add(UnlinkedConstOperation.pushReference); |
| 67 } else if (expr is InstanceCreationExpression) { | 126 } else if (expr is InstanceCreationExpression) { |
| 68 _serializeInstanceCreation(expr); | 127 _serializeInstanceCreation(expr); |
| 69 } else if (expr is ListLiteral) { | 128 } else if (expr is ListLiteral) { |
| 70 _serializeListLiteral(expr); | 129 _serializeListLiteral(expr); |
| 71 } else if (expr is MapLiteral) { | 130 } else if (expr is MapLiteral) { |
| 72 _serializeMapLiteral(expr); | 131 _serializeMapLiteral(expr); |
| 73 } else if (expr is MethodInvocation) { | 132 } else if (expr is MethodInvocation) { |
| 74 String name = expr.methodName.name; | 133 String name = expr.methodName.name; |
| 75 if (name != 'identical') { | 134 if (name != 'identical') { |
| 76 throw new _ConstExprSerializationError( | 135 throw new StateError('Only "identity" function invocation is allowed.'); |
| 77 'Only "identity" function invocation is allowed.'); | |
| 78 } | 136 } |
| 79 if (expr.argumentList == null || | 137 if (expr.argumentList == null || |
| 80 expr.argumentList.arguments.length != 2) { | 138 expr.argumentList.arguments.length != 2) { |
| 81 throw new _ConstExprSerializationError( | 139 throw new StateError( |
| 82 'The function "identity" requires exactly 2 arguments.'); | 140 'The function "identity" requires exactly 2 arguments.'); |
| 83 } | 141 } |
| 84 expr.argumentList.arguments.forEach(serialize); | 142 expr.argumentList.arguments.forEach(_serialize); |
| 85 operations.add(UnlinkedConstOperation.identical); | 143 operations.add(UnlinkedConstOperation.identical); |
| 86 } else if (expr is BinaryExpression) { | 144 } else if (expr is BinaryExpression) { |
| 87 _serializeBinaryExpression(expr); | 145 _serializeBinaryExpression(expr); |
| 88 } else if (expr is ConditionalExpression) { | 146 } else if (expr is ConditionalExpression) { |
| 89 serialize(expr.condition); | 147 _serialize(expr.condition); |
| 90 serialize(expr.thenExpression); | 148 _serialize(expr.thenExpression); |
| 91 serialize(expr.elseExpression); | 149 _serialize(expr.elseExpression); |
| 92 operations.add(UnlinkedConstOperation.conditional); | 150 operations.add(UnlinkedConstOperation.conditional); |
| 93 } else if (expr is PrefixExpression) { | 151 } else if (expr is PrefixExpression) { |
| 94 _serializePrefixExpression(expr); | 152 _serializePrefixExpression(expr); |
| 95 } else if (expr is PropertyAccess) { | 153 } else if (expr is PropertyAccess) { |
| 96 if (expr.target is! PrefixedIdentifier && | 154 if (expr.target is! PrefixedIdentifier && |
| 97 expr.propertyName.name == 'length') { | 155 expr.propertyName.name == 'length') { |
| 98 serialize(expr.target); | 156 _serialize(expr.target); |
| 99 operations.add(UnlinkedConstOperation.length); | 157 operations.add(UnlinkedConstOperation.length); |
| 100 } else { | 158 } else { |
| 101 references.add(serializePropertyAccess(expr)); | 159 references.add(serializePropertyAccess(expr)); |
| 102 operations.add(UnlinkedConstOperation.pushReference); | 160 operations.add(UnlinkedConstOperation.pushReference); |
| 103 } | 161 } |
| 104 } else if (expr is ParenthesizedExpression) { | 162 } else if (expr is ParenthesizedExpression) { |
| 105 serialize(expr.expression); | 163 _serialize(expr.expression); |
| 106 } else { | 164 } else { |
| 107 throw new _ConstExprSerializationError('Unknown expression type: $expr'); | 165 throw new StateError('Unknown expression type: $expr'); |
| 108 } | |
| 109 } | |
| 110 | |
| 111 /** | |
| 112 * Return [EntityRefBuilder] that corresponds to the given [constructor]. | |
| 113 */ | |
| 114 EntityRefBuilder serializeConstructorName(ConstructorName constructor); | |
| 115 | |
| 116 /** | |
| 117 * Return [EntityRefBuilder] that corresponds to the given [identifier]. | |
| 118 */ | |
| 119 EntityRefBuilder serializeIdentifier(Identifier identifier); | |
| 120 | |
| 121 /** | |
| 122 * Return [EntityRefBuilder] that corresponds to the given [access]. | |
| 123 */ | |
| 124 EntityRefBuilder serializePropertyAccess(PropertyAccess access); | |
| 125 | |
| 126 /** | |
| 127 * Return [EntityRefBuilder] that corresponds to the given [type]. | |
| 128 */ | |
| 129 EntityRefBuilder serializeType(TypeName type); | |
| 130 | |
| 131 /** | |
| 132 * Return the [UnlinkedConstBuilder] that corresponds to the state of this | |
| 133 * serializer. | |
| 134 */ | |
| 135 UnlinkedConstBuilder toBuilder() { | |
| 136 return new UnlinkedConstBuilder( | |
| 137 operations: operations, | |
| 138 ints: ints, | |
| 139 doubles: doubles, | |
| 140 strings: strings, | |
| 141 references: references); | |
| 142 } | |
| 143 | |
| 144 void _pushInt(int value) { | |
| 145 assert(value >= 0); | |
| 146 if (value >= (1 << 32)) { | |
| 147 int numOfComponents = 0; | |
| 148 ints.add(numOfComponents); | |
| 149 void pushComponents(int value) { | |
| 150 if (value >= (1 << 32)) { | |
| 151 pushComponents(value >> 32); | |
| 152 } | |
| 153 numOfComponents++; | |
| 154 ints.add(value & 0xFFFFFFFF); | |
| 155 } | |
| 156 pushComponents(value); | |
| 157 ints[ints.length - 1 - numOfComponents] = numOfComponents; | |
| 158 operations.add(UnlinkedConstOperation.pushLongInt); | |
| 159 } else { | |
| 160 operations.add(UnlinkedConstOperation.pushInt); | |
| 161 ints.add(value); | |
| 162 } | 166 } |
| 163 } | 167 } |
| 164 | 168 |
| 165 void _serializeBinaryExpression(BinaryExpression expr) { | 169 void _serializeBinaryExpression(BinaryExpression expr) { |
| 166 serialize(expr.leftOperand); | 170 _serialize(expr.leftOperand); |
| 167 serialize(expr.rightOperand); | 171 _serialize(expr.rightOperand); |
| 168 TokenType operator = expr.operator.type; | 172 TokenType operator = expr.operator.type; |
| 169 if (operator == TokenType.EQ_EQ) { | 173 if (operator == TokenType.EQ_EQ) { |
| 170 operations.add(UnlinkedConstOperation.equal); | 174 operations.add(UnlinkedConstOperation.equal); |
| 171 } else if (operator == TokenType.BANG_EQ) { | 175 } else if (operator == TokenType.BANG_EQ) { |
| 172 operations.add(UnlinkedConstOperation.notEqual); | 176 operations.add(UnlinkedConstOperation.notEqual); |
| 173 } else if (operator == TokenType.AMPERSAND_AMPERSAND) { | 177 } else if (operator == TokenType.AMPERSAND_AMPERSAND) { |
| 174 operations.add(UnlinkedConstOperation.and); | 178 operations.add(UnlinkedConstOperation.and); |
| 175 } else if (operator == TokenType.BAR_BAR) { | 179 } else if (operator == TokenType.BAR_BAR) { |
| 176 operations.add(UnlinkedConstOperation.or); | 180 operations.add(UnlinkedConstOperation.or); |
| 177 } else if (operator == TokenType.CARET) { | 181 } else if (operator == TokenType.CARET) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 198 operations.add(UnlinkedConstOperation.greater); | 202 operations.add(UnlinkedConstOperation.greater); |
| 199 } else if (operator == TokenType.LT) { | 203 } else if (operator == TokenType.LT) { |
| 200 operations.add(UnlinkedConstOperation.less); | 204 operations.add(UnlinkedConstOperation.less); |
| 201 } else if (operator == TokenType.GT_EQ) { | 205 } else if (operator == TokenType.GT_EQ) { |
| 202 operations.add(UnlinkedConstOperation.greaterEqual); | 206 operations.add(UnlinkedConstOperation.greaterEqual); |
| 203 } else if (operator == TokenType.LT_EQ) { | 207 } else if (operator == TokenType.LT_EQ) { |
| 204 operations.add(UnlinkedConstOperation.lessEqual); | 208 operations.add(UnlinkedConstOperation.lessEqual); |
| 205 } else if (operator == TokenType.PERCENT) { | 209 } else if (operator == TokenType.PERCENT) { |
| 206 operations.add(UnlinkedConstOperation.modulo); | 210 operations.add(UnlinkedConstOperation.modulo); |
| 207 } else { | 211 } else { |
| 208 throw new _ConstExprSerializationError('Unknown operator: $operator'); | 212 throw new StateError('Unknown operator: $operator'); |
| 209 } | 213 } |
| 210 } | 214 } |
| 211 | 215 |
| 212 void _serializeInstanceCreation(InstanceCreationExpression expr) { | 216 void _serializeInstanceCreation(InstanceCreationExpression expr) { |
| 213 ConstructorName constructor = expr.constructorName; | 217 ConstructorName constructor = expr.constructorName; |
| 214 List<Expression> arguments = expr.argumentList.arguments; | 218 List<Expression> arguments = expr.argumentList.arguments; |
| 215 // Serialize the arguments. | 219 // Serialize the arguments. |
| 216 List<String> argumentNames = <String>[]; | 220 List<String> argumentNames = <String>[]; |
| 217 arguments.forEach((arg) { | 221 arguments.forEach((arg) { |
| 218 if (arg is NamedExpression) { | 222 if (arg is NamedExpression) { |
| 219 argumentNames.add(arg.name.label.name); | 223 argumentNames.add(arg.name.label.name); |
| 220 serialize(arg.expression); | 224 _serialize(arg.expression); |
| 221 } else { | 225 } else { |
| 222 serialize(arg); | 226 _serialize(arg); |
| 223 } | 227 } |
| 224 }); | 228 }); |
| 225 // Add the op-code and numbers of named and positional arguments. | 229 // Add the op-code and numbers of named and positional arguments. |
| 226 operations.add(UnlinkedConstOperation.invokeConstructor); | 230 operations.add(UnlinkedConstOperation.invokeConstructor); |
| 227 ints.add(argumentNames.length); | 231 ints.add(argumentNames.length); |
| 228 strings.addAll(argumentNames); | 232 strings.addAll(argumentNames); |
| 229 ints.add(arguments.length - argumentNames.length); | 233 ints.add(arguments.length - argumentNames.length); |
| 230 // Serialize the reference. | 234 // Serialize the reference. |
| 231 references.add(serializeConstructorName(constructor)); | 235 references.add(serializeConstructorName(constructor)); |
| 232 } | 236 } |
| 233 | 237 |
| 234 void _serializeListLiteral(ListLiteral expr) { | 238 void _serializeListLiteral(ListLiteral expr) { |
| 235 List<Expression> elements = expr.elements; | 239 List<Expression> elements = expr.elements; |
| 236 elements.forEach(serialize); | 240 elements.forEach(_serialize); |
| 237 ints.add(elements.length); | 241 ints.add(elements.length); |
| 238 if (expr.typeArguments != null && | 242 if (expr.typeArguments != null && |
| 239 expr.typeArguments.arguments.length == 1) { | 243 expr.typeArguments.arguments.length == 1) { |
| 240 references.add(serializeType(expr.typeArguments.arguments[0])); | 244 references.add(serializeType(expr.typeArguments.arguments[0])); |
| 241 operations.add(UnlinkedConstOperation.makeTypedList); | 245 operations.add(UnlinkedConstOperation.makeTypedList); |
| 242 } else { | 246 } else { |
| 243 operations.add(UnlinkedConstOperation.makeUntypedList); | 247 operations.add(UnlinkedConstOperation.makeUntypedList); |
| 244 } | 248 } |
| 245 } | 249 } |
| 246 | 250 |
| 247 void _serializeMapLiteral(MapLiteral expr) { | 251 void _serializeMapLiteral(MapLiteral expr) { |
| 248 for (MapLiteralEntry entry in expr.entries) { | 252 for (MapLiteralEntry entry in expr.entries) { |
| 249 serialize(entry.key); | 253 _serialize(entry.key); |
| 250 serialize(entry.value); | 254 _serialize(entry.value); |
| 251 } | 255 } |
| 252 ints.add(expr.entries.length); | 256 ints.add(expr.entries.length); |
| 253 if (expr.typeArguments != null && | 257 if (expr.typeArguments != null && |
| 254 expr.typeArguments.arguments.length == 2) { | 258 expr.typeArguments.arguments.length == 2) { |
| 255 references.add(serializeType(expr.typeArguments.arguments[0])); | 259 references.add(serializeType(expr.typeArguments.arguments[0])); |
| 256 references.add(serializeType(expr.typeArguments.arguments[1])); | 260 references.add(serializeType(expr.typeArguments.arguments[1])); |
| 257 operations.add(UnlinkedConstOperation.makeTypedMap); | 261 operations.add(UnlinkedConstOperation.makeTypedMap); |
| 258 } else { | 262 } else { |
| 259 operations.add(UnlinkedConstOperation.makeUntypedMap); | 263 operations.add(UnlinkedConstOperation.makeUntypedMap); |
| 260 } | 264 } |
| 261 } | 265 } |
| 262 | 266 |
| 263 void _serializePrefixExpression(PrefixExpression expr) { | 267 void _serializePrefixExpression(PrefixExpression expr) { |
| 264 serialize(expr.operand); | 268 _serialize(expr.operand); |
| 265 TokenType operator = expr.operator.type; | 269 TokenType operator = expr.operator.type; |
| 266 if (operator == TokenType.BANG) { | 270 if (operator == TokenType.BANG) { |
| 267 operations.add(UnlinkedConstOperation.not); | 271 operations.add(UnlinkedConstOperation.not); |
| 268 } else if (operator == TokenType.MINUS) { | 272 } else if (operator == TokenType.MINUS) { |
| 269 operations.add(UnlinkedConstOperation.negate); | 273 operations.add(UnlinkedConstOperation.negate); |
| 270 } else if (operator == TokenType.TILDE) { | 274 } else if (operator == TokenType.TILDE) { |
| 271 operations.add(UnlinkedConstOperation.complement); | 275 operations.add(UnlinkedConstOperation.complement); |
| 272 } else { | 276 } else { |
| 273 throw new _ConstExprSerializationError('Unknown operator: $operator'); | 277 throw new StateError('Unknown operator: $operator'); |
| 274 } | 278 } |
| 275 } | 279 } |
| 276 | 280 |
| 277 void _serializeString(StringLiteral expr) { | 281 void _serializeString(StringLiteral expr) { |
| 278 if (expr is AdjacentStrings) { | 282 if (expr is AdjacentStrings) { |
| 279 if (expr.strings.every((string) => string is SimpleStringLiteral)) { | 283 if (expr.strings.every((string) => string is SimpleStringLiteral)) { |
| 280 operations.add(UnlinkedConstOperation.pushString); | 284 operations.add(UnlinkedConstOperation.pushString); |
| 281 strings.add(expr.stringValue); | 285 strings.add(expr.stringValue); |
| 282 } else { | 286 } else { |
| 283 expr.strings.forEach(_serializeString); | 287 expr.strings.forEach(_serializeString); |
| 284 operations.add(UnlinkedConstOperation.concatenate); | 288 operations.add(UnlinkedConstOperation.concatenate); |
| 285 ints.add(expr.strings.length); | 289 ints.add(expr.strings.length); |
| 286 } | 290 } |
| 287 } else if (expr is SimpleStringLiteral) { | 291 } else if (expr is SimpleStringLiteral) { |
| 288 operations.add(UnlinkedConstOperation.pushString); | 292 operations.add(UnlinkedConstOperation.pushString); |
| 289 strings.add(expr.value); | 293 strings.add(expr.value); |
| 290 } else { | 294 } else { |
| 291 StringInterpolation interpolation = expr as StringInterpolation; | 295 StringInterpolation interpolation = expr as StringInterpolation; |
| 292 for (InterpolationElement element in interpolation.elements) { | 296 for (InterpolationElement element in interpolation.elements) { |
| 293 if (element is InterpolationString) { | 297 if (element is InterpolationString) { |
| 294 operations.add(UnlinkedConstOperation.pushString); | 298 operations.add(UnlinkedConstOperation.pushString); |
| 295 strings.add(element.value); | 299 strings.add(element.value); |
| 296 } else { | 300 } else { |
| 297 serialize((element as InterpolationExpression).expression); | 301 _serialize((element as InterpolationExpression).expression); |
| 298 } | 302 } |
| 299 } | 303 } |
| 300 operations.add(UnlinkedConstOperation.concatenate); | 304 operations.add(UnlinkedConstOperation.concatenate); |
| 301 ints.add(interpolation.elements.length); | 305 ints.add(interpolation.elements.length); |
| 302 } | 306 } |
| 303 } | 307 } |
| 304 } | 308 } |
| 305 | |
| 306 /** | |
| 307 * Error that describes a problem during a constant expression serialization. | |
| 308 */ | |
| 309 class _ConstExprSerializationError { | |
| 310 final String message; | |
| 311 | |
| 312 _ConstExprSerializationError(this.message); | |
| 313 | |
| 314 @override | |
| 315 String toString() => message; | |
| 316 } | |
| OLD | NEW |