OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2014, 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 // This code was auto-generated, is not intended to be edited, and is subject to |
| 6 // significant change. Please see the README file for more information. |
| 7 |
| 8 library engine.constant; |
| 9 |
| 10 import 'dart:collection'; |
| 11 import 'java_core.dart'; |
| 12 import 'java_engine.dart' show ObjectUtilities; |
| 13 import 'source.dart' show Source; |
| 14 import 'error.dart' show AnalysisError, ErrorCode, CompileTimeErrorCode; |
| 15 import 'scanner.dart' show Token, TokenType; |
| 16 import 'ast.dart'; |
| 17 import 'element.dart'; |
| 18 import 'resolver.dart' show TypeProvider; |
| 19 import 'engine.dart' show AnalysisEngine; |
| 20 import 'utilities_dart.dart' show ParameterKind; |
| 21 import 'utilities_collection.dart'; |
| 22 |
| 23 /** |
| 24 * Instances of the class `BoolState` represent the state of an object represent
ing a boolean |
| 25 * value. |
| 26 */ |
| 27 class BoolState extends InstanceState { |
| 28 /** |
| 29 * The value of this instance. |
| 30 */ |
| 31 final bool value; |
| 32 |
| 33 /** |
| 34 * An instance representing the boolean value 'false'. |
| 35 */ |
| 36 static BoolState FALSE_STATE = new BoolState(false); |
| 37 |
| 38 /** |
| 39 * An instance representing the boolean value 'true'. |
| 40 */ |
| 41 static BoolState TRUE_STATE = new BoolState(true); |
| 42 |
| 43 /** |
| 44 * A state that can be used to represent a boolean whose value is not known. |
| 45 */ |
| 46 static BoolState UNKNOWN_VALUE = new BoolState(null); |
| 47 |
| 48 /** |
| 49 * Return the boolean state representing the given boolean value. |
| 50 * |
| 51 * @param value the value to be represented |
| 52 * @return the boolean state representing the given boolean value |
| 53 */ |
| 54 static BoolState from(bool value) => value ? BoolState.TRUE_STATE : BoolState.
FALSE_STATE; |
| 55 |
| 56 /** |
| 57 * Initialize a newly created state to represent the given value. |
| 58 * |
| 59 * @param value the value of this instance |
| 60 */ |
| 61 BoolState(this.value); |
| 62 |
| 63 @override |
| 64 BoolState convertToBool() => this; |
| 65 |
| 66 @override |
| 67 StringState convertToString() { |
| 68 if (value == null) { |
| 69 return StringState.UNKNOWN_VALUE; |
| 70 } |
| 71 return new StringState(value ? "true" : "false"); |
| 72 } |
| 73 |
| 74 @override |
| 75 BoolState equalEqual(InstanceState rightOperand) { |
| 76 assertBoolNumStringOrNull(rightOperand); |
| 77 if (value == null) { |
| 78 return UNKNOWN_VALUE; |
| 79 } |
| 80 if (rightOperand is BoolState) { |
| 81 bool rightValue = rightOperand.value; |
| 82 if (rightValue == null) { |
| 83 return UNKNOWN_VALUE; |
| 84 } |
| 85 return BoolState.from(identical(value, rightValue)); |
| 86 } else if (rightOperand is DynamicState) { |
| 87 return UNKNOWN_VALUE; |
| 88 } |
| 89 return FALSE_STATE; |
| 90 } |
| 91 |
| 92 @override |
| 93 bool operator ==(Object object) => object is BoolState && identical(value, obj
ect.value); |
| 94 |
| 95 @override |
| 96 String get typeName => "bool"; |
| 97 |
| 98 @override |
| 99 bool get hasExactValue => true; |
| 100 |
| 101 @override |
| 102 int get hashCode => value == null ? 0 : (value ? 2 : 3); |
| 103 |
| 104 /** |
| 105 * Return `true` if this object represents an object whose type is 'bool'. |
| 106 * |
| 107 * @return `true` if this object represents a boolean value |
| 108 */ |
| 109 @override |
| 110 bool get isBool => true; |
| 111 |
| 112 @override |
| 113 bool get isBoolNumStringOrNull => true; |
| 114 |
| 115 @override |
| 116 bool get isUnknown => value == null; |
| 117 |
| 118 @override |
| 119 BoolState logicalAnd(InstanceState rightOperand) { |
| 120 assertBool(rightOperand); |
| 121 if (value == null) { |
| 122 return UNKNOWN_VALUE; |
| 123 } |
| 124 return value ? rightOperand.convertToBool() : FALSE_STATE; |
| 125 } |
| 126 |
| 127 @override |
| 128 BoolState logicalNot() { |
| 129 if (value == null) { |
| 130 return UNKNOWN_VALUE; |
| 131 } |
| 132 return value ? FALSE_STATE : TRUE_STATE; |
| 133 } |
| 134 |
| 135 @override |
| 136 BoolState logicalOr(InstanceState rightOperand) { |
| 137 assertBool(rightOperand); |
| 138 if (value == null) { |
| 139 return UNKNOWN_VALUE; |
| 140 } |
| 141 return value ? TRUE_STATE : rightOperand.convertToBool(); |
| 142 } |
| 143 |
| 144 @override |
| 145 String toString() => value == null ? "-unknown-" : (value ? "true" : "false"); |
| 146 } |
| 147 |
| 148 /** |
| 149 * Instances of the class `ConstantEvaluator` evaluate constant expressions to p
roduce their |
| 150 * compile-time value. According to the Dart Language Specification: <blockquote
> A constant |
| 151 * expression is one of the following: |
| 152 * * A literal number. |
| 153 * * A literal boolean. |
| 154 * * A literal string where any interpolated expression is a compile-time consta
nt that evaluates |
| 155 * to a numeric, string or boolean value or to <b>null</b>. |
| 156 * * A literal symbol. |
| 157 * * <b>null</b>. |
| 158 * * A qualified reference to a static constant variable. |
| 159 * * An identifier expression that denotes a constant variable, class or type al
ias. |
| 160 * * A constant constructor invocation. |
| 161 * * A constant list literal. |
| 162 * * A constant map literal. |
| 163 * * A simple or qualified identifier denoting a top-level function or a static
method. |
| 164 * * A parenthesized expression <i>(e)</i> where <i>e</i> is a constant expressi
on. |
| 165 * * An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i> wh
ere |
| 166 * <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions and <i
>identical()</i> is |
| 167 * statically bound to the predefined dart function <i>identical()</i> discussed
above. |
| 168 * * An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> or
<i>e<sub>1</sub> |
| 169 * != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are
constant expressions |
| 170 * that evaluate to a numeric, string or boolean value. |
| 171 * * An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> && e<
sub>2</sub></i> or |
| 172 * <i>e<sub>1</sub> || e<sub>2</sub></i>, where <i>e</i>, <i>e1</sub></i> and <i
>e2</sub></i> are |
| 173 * constant expressions that evaluate to a boolean value. |
| 174 * * An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^ e<sub>2</su
b></i>, |
| 175 * <i>e<sub>1</sub> & e<sub>2</sub></i>, <i>e<sub>1</sub> | e<sub>2</sub></i
>, <i>e<sub>1</sub> |
| 176 * >> e<sub>2</sub></i> or <i>e<sub>1</sub> << e<sub>2</sub></i>, wh
ere <i>e</i>, |
| 177 * <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions that e
valuate to an |
| 178 * integer value or to <b>null</b>. |
| 179 * * An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> + e<sub>2</su
b></i>, |
| 180 * <i>e<sub>1</sub> -e<sub>2</sub></i>, <i>e<sub>1</sub> * e<sub>2</sub></i>, <i
>e<sub>1</sub> / |
| 181 * e<sub>2</sub></i>, <i>e<sub>1</sub> ~/ e<sub>2</sub></i>, <i>e<sub>1</sub> &g
t; |
| 182 * e<sub>2</sub></i>, <i>e<sub>1</sub> < e<sub>2</sub></i>, <i>e<sub>1</sub>
>= |
| 183 * e<sub>2</sub></i>, <i>e<sub>1</sub> <= e<sub>2</sub></i> or <i>e<sub>1</su
b> % |
| 184 * e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub><
/i> are constant |
| 185 * expressions that evaluate to a numeric value or to <b>null</b>. |
| 186 * * An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> : e<sub>3</sub><
/i> where |
| 187 * <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and <i>e<sub>3</sub></i> are const
ant expressions, and |
| 188 * <i>e<sub>1</sub></i> evaluates to a boolean value. |
| 189 * </blockquote> |
| 190 */ |
| 191 class ConstantEvaluator { |
| 192 /** |
| 193 * The source containing the expression(s) that will be evaluated. |
| 194 */ |
| 195 final Source _source; |
| 196 |
| 197 /** |
| 198 * The type provider used to access the known types. |
| 199 */ |
| 200 final TypeProvider _typeProvider; |
| 201 |
| 202 /** |
| 203 * Initialize a newly created evaluator to evaluate expressions in the given s
ource. |
| 204 * |
| 205 * @param source the source containing the expression(s) that will be evaluate
d |
| 206 * @param typeProvider the type provider used to access known types |
| 207 */ |
| 208 ConstantEvaluator(this._source, this._typeProvider); |
| 209 |
| 210 EvaluationResult evaluate(Expression expression) { |
| 211 EvaluationResultImpl result = expression.accept(new ConstantVisitor.con1(_ty
peProvider)); |
| 212 if (result is ValidResult) { |
| 213 return EvaluationResult.forValue(result.value); |
| 214 } |
| 215 List<AnalysisError> errors = new List<AnalysisError>(); |
| 216 for (ErrorResult_ErrorData data in (result as ErrorResult).errorData) { |
| 217 AstNode node = data.node; |
| 218 errors.add(new AnalysisError.con2(_source, node.offset, node.length, data.
errorCode, [])); |
| 219 } |
| 220 return EvaluationResult.forErrors(new List.from(errors)); |
| 221 } |
| 222 } |
| 223 |
| 224 /** |
| 225 * Instances of the class `ConstantFinder` are used to traverse the AST structur
es of all of |
| 226 * the compilation units being resolved and build a table mapping constant varia
ble elements to the |
| 227 * declarations of those variables. |
| 228 */ |
| 229 class ConstantFinder extends RecursiveAstVisitor<Object> { |
| 230 /** |
| 231 * A table mapping constant variable elements to the declarations of those var
iables. |
| 232 */ |
| 233 final HashMap<VariableElement, VariableDeclaration> variableMap = new HashMap<
VariableElement, VariableDeclaration>(); |
| 234 |
| 235 /** |
| 236 * A table mapping constant constructors to the declarations of those construc
tors. |
| 237 */ |
| 238 final HashMap<ConstructorElement, ConstructorDeclaration> constructorMap = new
HashMap<ConstructorElement, ConstructorDeclaration>(); |
| 239 |
| 240 /** |
| 241 * A collection of constant constructor invocations. |
| 242 */ |
| 243 final List<InstanceCreationExpression> constructorInvocations = new List<Insta
nceCreationExpression>(); |
| 244 |
| 245 @override |
| 246 Object visitConstructorDeclaration(ConstructorDeclaration node) { |
| 247 super.visitConstructorDeclaration(node); |
| 248 if (node.constKeyword != null) { |
| 249 ConstructorElement element = node.element; |
| 250 if (element != null) { |
| 251 constructorMap[element] = node; |
| 252 } |
| 253 } |
| 254 return null; |
| 255 } |
| 256 |
| 257 @override |
| 258 Object visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 259 super.visitInstanceCreationExpression(node); |
| 260 if (node.isConst) { |
| 261 constructorInvocations.add(node); |
| 262 } |
| 263 return null; |
| 264 } |
| 265 |
| 266 @override |
| 267 Object visitVariableDeclaration(VariableDeclaration node) { |
| 268 super.visitVariableDeclaration(node); |
| 269 Expression initializer = node.initializer; |
| 270 if (initializer != null && node.isConst) { |
| 271 VariableElement element = node.element; |
| 272 if (element != null) { |
| 273 variableMap[element] = node; |
| 274 } |
| 275 } |
| 276 return null; |
| 277 } |
| 278 } |
| 279 |
| 280 /** |
| 281 * Instances of the class `ConstantValueComputer` compute the values of constant
variables and |
| 282 * constant constructor invocations in one or more compilation units. The expect
ed usage pattern is |
| 283 * for the compilation units to be added to this computer using the method |
| 284 * [add] and then for the method [computeValues] to be invoked |
| 285 * exactly once. Any use of an instance after invoking the method [computeValues
] will |
| 286 * result in unpredictable behavior. |
| 287 */ |
| 288 class ConstantValueComputer { |
| 289 /** |
| 290 * Parameter to "fromEnvironment" methods that denotes the default value. |
| 291 */ |
| 292 static String _DEFAULT_VALUE_PARAM = "defaultValue"; |
| 293 |
| 294 /** |
| 295 * Source of RegExp matching declarable operator names. From sdk/lib/internal/
symbol.dart. |
| 296 */ |
| 297 static String _OPERATOR_RE = "(?:[\\-+*/%&|^]|\\[\\]=?|==|~/?|<[<=]?|>[>=]?|un
ary-)"; |
| 298 |
| 299 /** |
| 300 * Source of RegExp matching any public identifier. From sdk/lib/internal/symb
ol.dart. |
| 301 */ |
| 302 static String _PUBLIC_IDENTIFIER_RE = "(?!${ConstantValueComputer._RESERVED_WO
RD_RE}\\b(?!\\\$))[a-zA-Z\$][\\w\$]*"; |
| 303 |
| 304 /** |
| 305 * Source of RegExp matching Dart reserved words. From sdk/lib/internal/symbol
.dart. |
| 306 */ |
| 307 static String _RESERVED_WORD_RE = "(?:assert|break|c(?:a(?:se|tch)|lass|on(?:s
t|tinue))|d(?:efault|o)|e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|i[fns]|n(?:
ew|ull)|ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|r(?:ue|y))|v(?:ar|oid)|w
(?:hile|ith))"; |
| 308 |
| 309 /** |
| 310 * RegExp that validates a non-empty non-private symbol. From sdk/lib/internal
/symbol.dart. |
| 311 */ |
| 312 static RegExp _PUBLIC_SYMBOL_PATTERN = new RegExp("^(?:${ConstantValueComputer
._OPERATOR_RE}\$|${_PUBLIC_IDENTIFIER_RE}(?:=?\$|[.](?!\$)))+?\$"); |
| 313 |
| 314 /** |
| 315 * Determine whether the given string is a valid name for a public symbol (i.e
. whether it is |
| 316 * allowed for a call to the Symbol constructor). |
| 317 */ |
| 318 static bool isValidPublicSymbol(String name) => name.isEmpty || name == "void"
|| new JavaPatternMatcher(_PUBLIC_SYMBOL_PATTERN, name).matches(); |
| 319 |
| 320 /** |
| 321 * The type provider used to access the known types. |
| 322 */ |
| 323 TypeProvider typeProvider; |
| 324 |
| 325 /** |
| 326 * The object used to find constant variables and constant constructor invocat
ions in the |
| 327 * compilation units that were added. |
| 328 */ |
| 329 ConstantFinder _constantFinder = new ConstantFinder(); |
| 330 |
| 331 /** |
| 332 * A graph in which the nodes are the constants, and the edges are from each c
onstant to the other |
| 333 * constants that are referenced by it. |
| 334 */ |
| 335 DirectedGraph<AstNode> referenceGraph = new DirectedGraph<AstNode>(); |
| 336 |
| 337 /** |
| 338 * A table mapping constant variables to the declarations of those variables. |
| 339 */ |
| 340 HashMap<VariableElement, VariableDeclaration> _variableDeclarationMap; |
| 341 |
| 342 /** |
| 343 * A table mapping constant constructors to the declarations of those construc
tors. |
| 344 */ |
| 345 HashMap<ConstructorElement, ConstructorDeclaration> constructorDeclarationMap; |
| 346 |
| 347 /** |
| 348 * A collection of constant constructor invocations. |
| 349 */ |
| 350 List<InstanceCreationExpression> _constructorInvocations; |
| 351 |
| 352 /** |
| 353 * The set of variables declared on the command line using '-D'. |
| 354 */ |
| 355 final DeclaredVariables _declaredVariables; |
| 356 |
| 357 /** |
| 358 * Initialize a newly created constant value computer. |
| 359 * |
| 360 * @param typeProvider the type provider used to access known types |
| 361 * @param declaredVariables the set of variables declared on the command line
using '-D' |
| 362 */ |
| 363 ConstantValueComputer(TypeProvider typeProvider, this._declaredVariables) { |
| 364 this.typeProvider = typeProvider; |
| 365 } |
| 366 |
| 367 /** |
| 368 * Add the constants in the given compilation unit to the list of constants wh
ose value needs to |
| 369 * be computed. |
| 370 * |
| 371 * @param unit the compilation unit defining the constants to be added |
| 372 */ |
| 373 void add(CompilationUnit unit) { |
| 374 unit.accept(_constantFinder); |
| 375 } |
| 376 |
| 377 /** |
| 378 * Compute values for all of the constants in the compilation units that were
added. |
| 379 */ |
| 380 void computeValues() { |
| 381 _variableDeclarationMap = _constantFinder.variableMap; |
| 382 constructorDeclarationMap = _constantFinder.constructorMap; |
| 383 _constructorInvocations = _constantFinder.constructorInvocations; |
| 384 for (MapEntry<VariableElement, VariableDeclaration> entry in getMapEntrySet(
_variableDeclarationMap)) { |
| 385 VariableDeclaration declaration = entry.getValue(); |
| 386 ReferenceFinder referenceFinder = new ReferenceFinder(declaration, referen
ceGraph, _variableDeclarationMap, constructorDeclarationMap); |
| 387 referenceGraph.addNode(declaration); |
| 388 declaration.initializer.accept(referenceFinder); |
| 389 } |
| 390 for (MapEntry<ConstructorElement, ConstructorDeclaration> entry in getMapEnt
rySet(constructorDeclarationMap)) { |
| 391 ConstructorDeclaration declaration = entry.getValue(); |
| 392 ReferenceFinder referenceFinder = new ReferenceFinder(declaration, referen
ceGraph, _variableDeclarationMap, constructorDeclarationMap); |
| 393 referenceGraph.addNode(declaration); |
| 394 bool superInvocationFound = false; |
| 395 NodeList<ConstructorInitializer> initializers = declaration.initializers; |
| 396 for (ConstructorInitializer initializer in initializers) { |
| 397 if (initializer is SuperConstructorInvocation) { |
| 398 superInvocationFound = true; |
| 399 } |
| 400 initializer.accept(referenceFinder); |
| 401 } |
| 402 if (!superInvocationFound) { |
| 403 // No explicit superconstructor invocation found, so we need to manually
insert |
| 404 // a reference to the implicit superconstructor. |
| 405 InterfaceType superclass = (entry.getKey().returnType as InterfaceType).
superclass; |
| 406 if (superclass != null && !superclass.isObject) { |
| 407 ConstructorElement unnamedConstructor = superclass.element.unnamedCons
tructor; |
| 408 ConstructorDeclaration superConstructorDeclaration = findConstructorDe
claration(unnamedConstructor); |
| 409 if (superConstructorDeclaration != null) { |
| 410 referenceGraph.addEdge(declaration, superConstructorDeclaration); |
| 411 } |
| 412 } |
| 413 } |
| 414 for (FormalParameter parameter in declaration.parameters.parameters) { |
| 415 referenceGraph.addNode(parameter); |
| 416 referenceGraph.addEdge(declaration, parameter); |
| 417 if (parameter is DefaultFormalParameter) { |
| 418 Expression defaultValue = parameter.defaultValue; |
| 419 if (defaultValue != null) { |
| 420 ReferenceFinder parameterReferenceFinder = new ReferenceFinder(param
eter, referenceGraph, _variableDeclarationMap, constructorDeclarationMap); |
| 421 defaultValue.accept(parameterReferenceFinder); |
| 422 } |
| 423 } |
| 424 } |
| 425 } |
| 426 for (InstanceCreationExpression expression in _constructorInvocations) { |
| 427 referenceGraph.addNode(expression); |
| 428 ConstructorElement constructor = expression.staticElement; |
| 429 if (constructor == null) { |
| 430 break; |
| 431 } |
| 432 constructor = _followConstantRedirectionChain(constructor); |
| 433 ConstructorDeclaration declaration = findConstructorDeclaration(constructo
r); |
| 434 // An instance creation expression depends both on the constructor and the
arguments passed |
| 435 // to it. |
| 436 ReferenceFinder referenceFinder = new ReferenceFinder(expression, referenc
eGraph, _variableDeclarationMap, constructorDeclarationMap); |
| 437 if (declaration != null) { |
| 438 referenceGraph.addEdge(expression, declaration); |
| 439 } |
| 440 expression.argumentList.accept(referenceFinder); |
| 441 } |
| 442 List<List<AstNode>> topologicalSort = referenceGraph.computeTopologicalSort(
); |
| 443 for (List<AstNode> constantsInCycle in topologicalSort) { |
| 444 if (constantsInCycle.length == 1) { |
| 445 _computeValueFor(constantsInCycle[0]); |
| 446 } else { |
| 447 for (AstNode constant in constantsInCycle) { |
| 448 _generateCycleError(constantsInCycle, constant); |
| 449 } |
| 450 } |
| 451 } |
| 452 } |
| 453 |
| 454 /** |
| 455 * This method is called just before computing the constant value associated w
ith an AST node. |
| 456 * Unit tests will override this method to introduce additional error checking
. |
| 457 */ |
| 458 void beforeComputeValue(AstNode constNode) { |
| 459 } |
| 460 |
| 461 /** |
| 462 * This method is called just before getting the constant initializers associa
ted with a |
| 463 * constructor AST node. Unit tests will override this method to introduce add
itional error |
| 464 * checking. |
| 465 */ |
| 466 void beforeGetConstantInitializers(ConstructorElement constructor) { |
| 467 } |
| 468 |
| 469 /** |
| 470 * This method is called just before getting a parameter's default value. Unit
tests will override |
| 471 * this method to introduce additional error checking. |
| 472 */ |
| 473 void beforeGetParameterDefault(ParameterElement parameter) { |
| 474 } |
| 475 |
| 476 /** |
| 477 * Create the ConstantVisitor used to evaluate constants. Unit tests will over
ride this method to |
| 478 * introduce additional error checking. |
| 479 */ |
| 480 ConstantVisitor createConstantVisitor() => new ConstantVisitor.con1(typeProvid
er); |
| 481 |
| 482 ConstructorDeclaration findConstructorDeclaration(ConstructorElement construct
or) => constructorDeclarationMap[_getConstructorBase(constructor)]; |
| 483 |
| 484 /** |
| 485 * Check that the arguments to a call to fromEnvironment() are correct. |
| 486 * |
| 487 * @param arguments the AST nodes of the arguments. |
| 488 * @param argumentValues the values of the unnamed arguments. |
| 489 * @param namedArgumentValues the values of the named arguments. |
| 490 * @param expectedDefaultValueType the allowed type of the "defaultValue" para
meter (if present). |
| 491 * Note: "defaultValue" is always allowed to be null. |
| 492 * @return true if the arguments are correct, false if there is an error. |
| 493 */ |
| 494 bool _checkFromEnvironmentArguments(NodeList<Expression> arguments, List<DartO
bjectImpl> argumentValues, HashMap<String, DartObjectImpl> namedArgumentValues,
InterfaceType expectedDefaultValueType) { |
| 495 int argumentCount = arguments.length; |
| 496 if (argumentCount < 1 || argumentCount > 2) { |
| 497 return false; |
| 498 } |
| 499 if (arguments[0] is NamedExpression) { |
| 500 return false; |
| 501 } |
| 502 if (!identical(argumentValues[0].type, typeProvider.stringType)) { |
| 503 return false; |
| 504 } |
| 505 if (argumentCount == 2) { |
| 506 if (arguments[1] is! NamedExpression) { |
| 507 return false; |
| 508 } |
| 509 if (!((arguments[1] as NamedExpression).name.label.name == _DEFAULT_VALUE_
PARAM)) { |
| 510 return false; |
| 511 } |
| 512 InterfaceType defaultValueType = namedArgumentValues[_DEFAULT_VALUE_PARAM]
.type; |
| 513 if (!(identical(defaultValueType, expectedDefaultValueType) || identical(d
efaultValueType, typeProvider.nullType))) { |
| 514 return false; |
| 515 } |
| 516 } |
| 517 return true; |
| 518 } |
| 519 |
| 520 /** |
| 521 * Check that the arguments to a call to Symbol() are correct. |
| 522 * |
| 523 * @param arguments the AST nodes of the arguments. |
| 524 * @param argumentValues the values of the unnamed arguments. |
| 525 * @param namedArgumentValues the values of the named arguments. |
| 526 * @return true if the arguments are correct, false if there is an error. |
| 527 */ |
| 528 bool _checkSymbolArguments(NodeList<Expression> arguments, List<DartObjectImpl
> argumentValues, HashMap<String, DartObjectImpl> namedArgumentValues) { |
| 529 if (arguments.length != 1) { |
| 530 return false; |
| 531 } |
| 532 if (arguments[0] is NamedExpression) { |
| 533 return false; |
| 534 } |
| 535 if (!identical(argumentValues[0].type, typeProvider.stringType)) { |
| 536 return false; |
| 537 } |
| 538 String name = argumentValues[0].stringValue; |
| 539 return isValidPublicSymbol(name); |
| 540 } |
| 541 |
| 542 /** |
| 543 * Compute a value for the given constant. |
| 544 * |
| 545 * @param constNode the constant for which a value is to be computed |
| 546 */ |
| 547 void _computeValueFor(AstNode constNode) { |
| 548 beforeComputeValue(constNode); |
| 549 if (constNode is VariableDeclaration) { |
| 550 VariableDeclaration declaration = constNode; |
| 551 Element element = declaration.element; |
| 552 EvaluationResultImpl result = declaration.initializer.accept(createConstan
tVisitor()); |
| 553 (element as VariableElementImpl).evaluationResult = result; |
| 554 } else if (constNode is InstanceCreationExpression) { |
| 555 InstanceCreationExpression expression = constNode; |
| 556 ConstructorElement constructor = expression.staticElement; |
| 557 if (constructor == null) { |
| 558 // Couldn't resolve the constructor so we can't compute a value. No pro
blem--the error |
| 559 // has already been reported. |
| 560 return; |
| 561 } |
| 562 ConstantVisitor constantVisitor = createConstantVisitor(); |
| 563 EvaluationResultImpl result = _evaluateConstructorCall(constNode, expressi
on.argumentList.arguments, constructor, constantVisitor); |
| 564 expression.evaluationResult = result; |
| 565 } else if (constNode is ConstructorDeclaration) { |
| 566 ConstructorDeclaration declaration = constNode; |
| 567 NodeList<ConstructorInitializer> initializers = declaration.initializers; |
| 568 ConstructorElementImpl constructor = declaration.element as ConstructorEle
mentImpl; |
| 569 constructor.constantInitializers = new ConstantValueComputer_InitializerCl
oner().cloneNodeList(initializers); |
| 570 } else if (constNode is FormalParameter) { |
| 571 if (constNode is DefaultFormalParameter) { |
| 572 DefaultFormalParameter parameter = constNode; |
| 573 ParameterElement element = parameter.element; |
| 574 Expression defaultValue = parameter.defaultValue; |
| 575 if (defaultValue != null) { |
| 576 EvaluationResultImpl result = defaultValue.accept(createConstantVisito
r()); |
| 577 (element as ParameterElementImpl).evaluationResult = result; |
| 578 } |
| 579 } |
| 580 } else { |
| 581 // Should not happen. |
| 582 AnalysisEngine.instance.logger.logError("Constant value computer trying to
compute the value of a node which is not a VariableDeclaration, InstanceCreatio
nExpression, FormalParameter, or ConstructorDeclaration"); |
| 583 return; |
| 584 } |
| 585 } |
| 586 |
| 587 /** |
| 588 * Evaluate a call to fromEnvironment() on the bool, int, or String class. |
| 589 * |
| 590 * @param environmentValue Value fetched from the environment |
| 591 * @param builtInDefaultValue Value that should be used as the default if no "
defaultValue" |
| 592 * argument appears in [namedArgumentValues]. |
| 593 * @param namedArgumentValues Named parameters passed to fromEnvironment() |
| 594 * @return A [ValidResult] object corresponding to the evaluated result |
| 595 */ |
| 596 ValidResult _computeValueFromEnvironment(DartObject environmentValue, DartObje
ctImpl builtInDefaultValue, HashMap<String, DartObjectImpl> namedArgumentValues)
{ |
| 597 DartObjectImpl value = environmentValue as DartObjectImpl; |
| 598 if (value.isUnknown || value.isNull) { |
| 599 // The name either doesn't exist in the environment or we couldn't parse t
he corresponding |
| 600 // value. If the code supplied an explicit default, use it. |
| 601 if (namedArgumentValues.containsKey(_DEFAULT_VALUE_PARAM)) { |
| 602 value = namedArgumentValues[_DEFAULT_VALUE_PARAM]; |
| 603 } else if (value.isNull) { |
| 604 // The code didn't supply an explicit default. The name exists in the e
nvironment but |
| 605 // we couldn't parse the corresponding value. So use the built-in defau
lt value, because |
| 606 // this is what the VM does. |
| 607 value = builtInDefaultValue; |
| 608 } else { |
| 609 } |
| 610 } |
| 611 return new ValidResult(value); |
| 612 } |
| 613 |
| 614 EvaluationResultImpl _evaluateConstructorCall(AstNode node, NodeList<Expressio
n> arguments, ConstructorElement constructor, ConstantVisitor constantVisitor) { |
| 615 int argumentCount = arguments.length; |
| 616 List<DartObjectImpl> argumentValues = new List<DartObjectImpl>(argumentCount
); |
| 617 HashMap<String, DartObjectImpl> namedArgumentValues = new HashMap<String, Da
rtObjectImpl>(); |
| 618 for (int i = 0; i < argumentCount; i++) { |
| 619 Expression argument = arguments[i]; |
| 620 if (argument is NamedExpression) { |
| 621 NamedExpression namedExpression = argument; |
| 622 String name = namedExpression.name.label.name; |
| 623 namedArgumentValues[name] = constantVisitor._valueOf(namedExpression.exp
ression); |
| 624 argumentValues[i] = constantVisitor.null2; |
| 625 } else { |
| 626 argumentValues[i] = constantVisitor._valueOf(argument); |
| 627 } |
| 628 } |
| 629 constructor = _followConstantRedirectionChain(constructor); |
| 630 InterfaceType definingClass = constructor.returnType as InterfaceType; |
| 631 if (constructor.isFactory) { |
| 632 // We couldn't find a non-factory constructor. See if it's because we rea
ched an external |
| 633 // const factory constructor that we can emulate. |
| 634 if (constructor.name == "fromEnvironment") { |
| 635 if (!_checkFromEnvironmentArguments(arguments, argumentValues, namedArgu
mentValues, definingClass)) { |
| 636 return new ErrorResult.con1(node, CompileTimeErrorCode.CONST_EVAL_THRO
WS_EXCEPTION); |
| 637 } |
| 638 String variableName = argumentCount < 1 ? null : argumentValues[0].strin
gValue; |
| 639 if (identical(definingClass, typeProvider.boolType)) { |
| 640 DartObject valueFromEnvironment; |
| 641 valueFromEnvironment = _declaredVariables.getBool(typeProvider, variab
leName); |
| 642 return _computeValueFromEnvironment(valueFromEnvironment, new DartObje
ctImpl(typeProvider.boolType, BoolState.FALSE_STATE), namedArgumentValues); |
| 643 } else if (identical(definingClass, typeProvider.intType)) { |
| 644 DartObject valueFromEnvironment; |
| 645 valueFromEnvironment = _declaredVariables.getInt(typeProvider, variabl
eName); |
| 646 return _computeValueFromEnvironment(valueFromEnvironment, new DartObje
ctImpl(typeProvider.nullType, NullState.NULL_STATE), namedArgumentValues); |
| 647 } else if (identical(definingClass, typeProvider.stringType)) { |
| 648 DartObject valueFromEnvironment; |
| 649 valueFromEnvironment = _declaredVariables.getString(typeProvider, vari
ableName); |
| 650 return _computeValueFromEnvironment(valueFromEnvironment, new DartObje
ctImpl(typeProvider.nullType, NullState.NULL_STATE), namedArgumentValues); |
| 651 } |
| 652 } else if (constructor.name == "" && identical(definingClass, typeProvider
.symbolType) && argumentCount == 1) { |
| 653 if (!_checkSymbolArguments(arguments, argumentValues, namedArgumentValue
s)) { |
| 654 return new ErrorResult.con1(node, CompileTimeErrorCode.CONST_EVAL_THRO
WS_EXCEPTION); |
| 655 } |
| 656 String argumentValue = argumentValues[0].stringValue; |
| 657 return constantVisitor._valid(definingClass, new SymbolState(argumentVal
ue)); |
| 658 } |
| 659 // Either it's an external const factory constructor that we can't emulate
, or an error |
| 660 // occurred (a cycle, or a const constructor trying to delegate to a non-c
onst constructor). |
| 661 // In the former case, the best we can do is consider it an unknown value.
In the latter |
| 662 // case, the error has already been reported, so considering it an unknown
value will |
| 663 // suppress further errors. |
| 664 return constantVisitor._validWithUnknownValue(definingClass); |
| 665 } |
| 666 beforeGetConstantInitializers(constructor); |
| 667 ConstructorElementImpl constructorBase = _getConstructorBase(constructor) as
ConstructorElementImpl; |
| 668 List<ConstructorInitializer> initializers = constructorBase.constantInitiali
zers; |
| 669 if (initializers == null) { |
| 670 // This can happen in some cases where there are compile errors in the cod
e being analyzed |
| 671 // (for example if the code is trying to create a const instance using a n
on-const |
| 672 // constructor, or the node we're visiting is involved in a cycle). The e
rror has already |
| 673 // been reported, so consider it an unknown value to suppress further erro
rs. |
| 674 return constantVisitor._validWithUnknownValue(definingClass); |
| 675 } |
| 676 HashMap<String, DartObjectImpl> fieldMap = new HashMap<String, DartObjectImp
l>(); |
| 677 HashMap<String, DartObjectImpl> parameterMap = new HashMap<String, DartObjec
tImpl>(); |
| 678 List<ParameterElement> parameters = constructorBase.parameters; |
| 679 int parameterCount = parameters.length; |
| 680 for (int i = 0; i < parameterCount; i++) { |
| 681 ParameterElement parameter = parameters[i]; |
| 682 while (parameter is ParameterMember) { |
| 683 parameter = (parameter as ParameterMember).baseElement; |
| 684 } |
| 685 DartObjectImpl argumentValue = null; |
| 686 if (parameter.parameterKind == ParameterKind.NAMED) { |
| 687 argumentValue = namedArgumentValues[parameter.name]; |
| 688 } else if (i < argumentCount) { |
| 689 argumentValue = argumentValues[i]; |
| 690 } |
| 691 if (argumentValue == null && parameter is ParameterElementImpl) { |
| 692 // The parameter is an optional positional parameter for which no value
was provided, so |
| 693 // use the default value. |
| 694 beforeGetParameterDefault(parameter); |
| 695 EvaluationResultImpl evaluationResult = (parameter as ParameterElementIm
pl).evaluationResult; |
| 696 if (evaluationResult is ValidResult) { |
| 697 argumentValue = evaluationResult.value; |
| 698 } else if (evaluationResult == null) { |
| 699 // No default was provided, so the default value is null. |
| 700 argumentValue = constantVisitor.null2; |
| 701 } |
| 702 } |
| 703 if (argumentValue != null) { |
| 704 if (parameter.isInitializingFormal) { |
| 705 FieldElement field = (parameter as FieldFormalParameterElement).field; |
| 706 if (field != null) { |
| 707 String fieldName = field.name; |
| 708 fieldMap[fieldName] = argumentValue; |
| 709 } |
| 710 } else { |
| 711 String name = parameter.name; |
| 712 parameterMap[name] = argumentValue; |
| 713 } |
| 714 } |
| 715 } |
| 716 ConstantVisitor initializerVisitor = new ConstantVisitor.con2(typeProvider,
parameterMap); |
| 717 String superName = null; |
| 718 NodeList<Expression> superArguments = null; |
| 719 for (ConstructorInitializer initializer in initializers) { |
| 720 if (initializer is ConstructorFieldInitializer) { |
| 721 ConstructorFieldInitializer constructorFieldInitializer = initializer; |
| 722 Expression initializerExpression = constructorFieldInitializer.expressio
n; |
| 723 EvaluationResultImpl evaluationResult = initializerExpression.accept(ini
tializerVisitor); |
| 724 if (evaluationResult is ValidResult) { |
| 725 DartObjectImpl value = evaluationResult.value; |
| 726 String fieldName = constructorFieldInitializer.fieldName.name; |
| 727 fieldMap[fieldName] = value; |
| 728 } |
| 729 } else if (initializer is SuperConstructorInvocation) { |
| 730 SuperConstructorInvocation superConstructorInvocation = initializer; |
| 731 SimpleIdentifier name = superConstructorInvocation.constructorName; |
| 732 if (name != null) { |
| 733 superName = name.name; |
| 734 } |
| 735 superArguments = superConstructorInvocation.argumentList.arguments; |
| 736 } |
| 737 } |
| 738 // Evaluate explicit or implicit call to super(). |
| 739 InterfaceType superclass = definingClass.superclass; |
| 740 if (superclass != null && !superclass.isObject) { |
| 741 ConstructorElement superConstructor = superclass.lookUpConstructor(superNa
me, constructor.library); |
| 742 if (superConstructor != null) { |
| 743 if (superArguments == null) { |
| 744 superArguments = new NodeList<Expression>(null); |
| 745 } |
| 746 _evaluateSuperConstructorCall(node, fieldMap, superConstructor, superArg
uments, initializerVisitor); |
| 747 } |
| 748 } |
| 749 return constantVisitor._valid(definingClass, new GenericState(fieldMap)); |
| 750 } |
| 751 |
| 752 void _evaluateSuperConstructorCall(AstNode node, HashMap<String, DartObjectImp
l> fieldMap, ConstructorElement superConstructor, NodeList<Expression> superArgu
ments, ConstantVisitor initializerVisitor) { |
| 753 if (superConstructor != null && superConstructor.isConst) { |
| 754 EvaluationResultImpl evaluationResult = _evaluateConstructorCall(node, sup
erArguments, superConstructor, initializerVisitor); |
| 755 if (evaluationResult is ValidResult) { |
| 756 ValidResult validResult = evaluationResult; |
| 757 fieldMap[GenericState.SUPERCLASS_FIELD] = validResult.value; |
| 758 } |
| 759 } |
| 760 } |
| 761 |
| 762 /** |
| 763 * Attempt to follow the chain of factory redirections until a constructor is
reached which is not |
| 764 * a const factory constructor. |
| 765 * |
| 766 * @return the constant constructor which terminates the chain of factory redi
rections, if the |
| 767 * chain terminates. If there is a problem (e.g. a redirection can't b
e found, or a cycle |
| 768 * is encountered), the chain will be followed as far as possible and
then a const factory |
| 769 * constructor will be returned. |
| 770 */ |
| 771 ConstructorElement _followConstantRedirectionChain(ConstructorElement construc
tor) { |
| 772 HashSet<ConstructorElement> constructorsVisited = new HashSet<ConstructorEle
ment>(); |
| 773 while (constructor.isFactory) { |
| 774 if (identical(constructor.enclosingElement.type, typeProvider.symbolType))
{ |
| 775 // The dart:core.Symbol has a const factory constructor that redirects t
o |
| 776 // dart:_internal.Symbol. That in turn redirects to an external const c
onstructor, which |
| 777 // we won't be able to evaluate. So stop following the chain of redirec
tions at |
| 778 // dart:core.Symbol, and let [evaluateInstanceCreationExpression] handle
it specially. |
| 779 break; |
| 780 } |
| 781 constructorsVisited.add(constructor); |
| 782 ConstructorElement redirectedConstructor = constructor.redirectedConstruct
or; |
| 783 if (redirectedConstructor == null) { |
| 784 // This can happen if constructor is an external factory constructor. |
| 785 break; |
| 786 } |
| 787 if (!redirectedConstructor.isConst) { |
| 788 // Delegating to a non-const constructor--this is not allowed (and |
| 789 // is checked elsewhere--see [ErrorVerifier.checkForRedirectToNonConstCo
nstructor()]). |
| 790 break; |
| 791 } |
| 792 if (constructorsVisited.contains(redirectedConstructor)) { |
| 793 // Cycle in redirecting factory constructors--this is not allowed |
| 794 // and is checked elsewhere--see [ErrorVerifier.checkForRecursiveFactory
Redirect()]). |
| 795 break; |
| 796 } |
| 797 constructor = redirectedConstructor; |
| 798 } |
| 799 return constructor; |
| 800 } |
| 801 |
| 802 /** |
| 803 * Generate an error indicating that the given constant is not a valid compile
-time constant |
| 804 * because it references at least one of the constants in the given cycle, eac
h of which directly |
| 805 * or indirectly references the constant. |
| 806 * |
| 807 * @param constantsInCycle the constants in the cycle that includes the given
constant |
| 808 * @param constant the constant that is not a valid compile-time constant |
| 809 */ |
| 810 void _generateCycleError(List<AstNode> constantsInCycle, AstNode constant) { |
| 811 } |
| 812 |
| 813 ConstructorElement _getConstructorBase(ConstructorElement constructor) { |
| 814 while (constructor is ConstructorMember) { |
| 815 constructor = (constructor as ConstructorMember).baseElement; |
| 816 } |
| 817 return constructor; |
| 818 } |
| 819 } |
| 820 |
| 821 /** |
| 822 * [AstCloner] that copies the necessary information from the AST to allow const
constructor |
| 823 * initializers to be evaluated. |
| 824 */ |
| 825 class ConstantValueComputer_InitializerCloner extends AstCloner { |
| 826 @override |
| 827 InstanceCreationExpression visitInstanceCreationExpression(InstanceCreationExp
ression node) { |
| 828 // All we need is the evaluation result, and the keyword so that we know whe
ther it's const. |
| 829 InstanceCreationExpression expression = new InstanceCreationExpression(node.
keyword, null, null); |
| 830 expression.evaluationResult = node.evaluationResult; |
| 831 return expression; |
| 832 } |
| 833 |
| 834 @override |
| 835 SimpleIdentifier visitSimpleIdentifier(SimpleIdentifier node) { |
| 836 SimpleIdentifier identifier = super.visitSimpleIdentifier(node); |
| 837 identifier.staticElement = node.staticElement; |
| 838 return identifier; |
| 839 } |
| 840 |
| 841 @override |
| 842 SuperConstructorInvocation visitSuperConstructorInvocation(SuperConstructorInv
ocation node) { |
| 843 SuperConstructorInvocation invocation = super.visitSuperConstructorInvocatio
n(node); |
| 844 invocation.staticElement = node.staticElement; |
| 845 return invocation; |
| 846 } |
| 847 } |
| 848 |
| 849 /** |
| 850 * Instances of the class `ConstantVisitor` evaluate constant expressions to pro
duce their |
| 851 * compile-time value. According to the Dart Language Specification: <blockquote
> A constant |
| 852 * expression is one of the following: |
| 853 * * A literal number. |
| 854 * * A literal boolean. |
| 855 * * A literal string where any interpolated expression is a compile-time consta
nt that evaluates |
| 856 * to a numeric, string or boolean value or to <b>null</b>. |
| 857 * * A literal symbol. |
| 858 * * <b>null</b>. |
| 859 * * A qualified reference to a static constant variable. |
| 860 * * An identifier expression that denotes a constant variable, class or type al
ias. |
| 861 * * A constant constructor invocation. |
| 862 * * A constant list literal. |
| 863 * * A constant map literal. |
| 864 * * A simple or qualified identifier denoting a top-level function or a static
method. |
| 865 * * A parenthesized expression <i>(e)</i> where <i>e</i> is a constant expressi
on. |
| 866 * * An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i> wh
ere |
| 867 * <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions and <i
>identical()</i> is |
| 868 * statically bound to the predefined dart function <i>identical()</i> discussed
above. |
| 869 * * An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i> or
<i>e<sub>1</sub> |
| 870 * != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are
constant expressions |
| 871 * that evaluate to a numeric, string or boolean value. |
| 872 * * An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> && e<
sub>2</sub></i> or |
| 873 * <i>e<sub>1</sub> || e<sub>2</sub></i>, where <i>e</i>, <i>e1</sub></i> and <i
>e2</sub></i> are |
| 874 * constant expressions that evaluate to a boolean value. |
| 875 * * An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^ e<sub>2</su
b></i>, |
| 876 * <i>e<sub>1</sub> & e<sub>2</sub></i>, <i>e<sub>1</sub> | e<sub>2</sub></i
>, <i>e<sub>1</sub> |
| 877 * >> e<sub>2</sub></i> or <i>e<sub>1</sub> << e<sub>2</sub></i>, wh
ere <i>e</i>, |
| 878 * <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions that e
valuate to an |
| 879 * integer value or to <b>null</b>. |
| 880 * * An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub> + e<sub>2</su
b></i>, |
| 881 * <i>e<sub>1</sub> - e<sub>2</sub></i>, <i>e<sub>1</sub> * e<sub>2</sub></i>, <
i>e<sub>1</sub> / |
| 882 * e<sub>2</sub></i>, <i>e<sub>1</sub> ~/ e<sub>2</sub></i>, <i>e<sub>1</sub> &g
t; |
| 883 * e<sub>2</sub></i>, <i>e<sub>1</sub> < e<sub>2</sub></i>, <i>e<sub>1</sub>
>= |
| 884 * e<sub>2</sub></i>, <i>e<sub>1</sub> <= e<sub>2</sub></i> or <i>e<sub>1</su
b> % |
| 885 * e<sub>2</sub></i>, where <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub><
/i> are constant |
| 886 * expressions that evaluate to a numeric value or to <b>null</b>. |
| 887 * * An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> : e<sub>3</sub><
/i> where |
| 888 * <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and <i>e<sub>3</sub></i> are const
ant expressions, and |
| 889 * <i>e<sub>1</sub></i> evaluates to a boolean value. |
| 890 * </blockquote> |
| 891 */ |
| 892 class ConstantVisitor extends UnifyingAstVisitor<EvaluationResultImpl> { |
| 893 /** |
| 894 * The type provider used to access the known types. |
| 895 */ |
| 896 final TypeProvider _typeProvider; |
| 897 |
| 898 /** |
| 899 * An shared object representing the value 'null'. |
| 900 */ |
| 901 DartObjectImpl _nullObject; |
| 902 |
| 903 HashMap<String, DartObjectImpl> _lexicalEnvironment; |
| 904 |
| 905 /** |
| 906 * Initialize a newly created constant visitor. |
| 907 * |
| 908 * @param typeProvider the type provider used to access known types |
| 909 * @param lexicalEnvironment values which should override simpleIdentifiers, o
r null if no |
| 910 * overriding is necessary. |
| 911 */ |
| 912 ConstantVisitor.con1(this._typeProvider) { |
| 913 this._lexicalEnvironment = null; |
| 914 } |
| 915 |
| 916 /** |
| 917 * Initialize a newly created constant visitor. |
| 918 * |
| 919 * @param typeProvider the type provider used to access known types |
| 920 * @param lexicalEnvironment values which should override simpleIdentifiers, o
r null if no |
| 921 * overriding is necessary. |
| 922 */ |
| 923 ConstantVisitor.con2(this._typeProvider, HashMap<String, DartObjectImpl> lexic
alEnvironment) { |
| 924 this._lexicalEnvironment = lexicalEnvironment; |
| 925 } |
| 926 |
| 927 @override |
| 928 EvaluationResultImpl visitAdjacentStrings(AdjacentStrings node) { |
| 929 EvaluationResultImpl result = null; |
| 930 for (StringLiteral string in node.strings) { |
| 931 if (result == null) { |
| 932 result = string.accept(this); |
| 933 } else { |
| 934 result = result.concatenate(_typeProvider, node, string.accept(this)); |
| 935 } |
| 936 } |
| 937 return result; |
| 938 } |
| 939 |
| 940 @override |
| 941 EvaluationResultImpl visitBinaryExpression(BinaryExpression node) { |
| 942 EvaluationResultImpl leftResult = node.leftOperand.accept(this); |
| 943 EvaluationResultImpl rightResult = node.rightOperand.accept(this); |
| 944 TokenType operatorType = node.operator.type; |
| 945 // 'null' is almost never good operand |
| 946 if (operatorType != TokenType.BANG_EQ && operatorType != TokenType.EQ_EQ) { |
| 947 if (leftResult is ValidResult && leftResult.isNull || rightResult is Valid
Result && rightResult.isNull) { |
| 948 return _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION); |
| 949 } |
| 950 } |
| 951 // evaluate operator |
| 952 while (true) { |
| 953 if (operatorType == TokenType.AMPERSAND) { |
| 954 return leftResult.bitAnd(_typeProvider, node, rightResult); |
| 955 } else if (operatorType == TokenType.AMPERSAND_AMPERSAND) { |
| 956 return leftResult.logicalAnd(_typeProvider, node, rightResult); |
| 957 } else if (operatorType == TokenType.BANG_EQ) { |
| 958 return leftResult.notEqual(_typeProvider, node, rightResult); |
| 959 } else if (operatorType == TokenType.BAR) { |
| 960 return leftResult.bitOr(_typeProvider, node, rightResult); |
| 961 } else if (operatorType == TokenType.BAR_BAR) { |
| 962 return leftResult.logicalOr(_typeProvider, node, rightResult); |
| 963 } else if (operatorType == TokenType.CARET) { |
| 964 return leftResult.bitXor(_typeProvider, node, rightResult); |
| 965 } else if (operatorType == TokenType.EQ_EQ) { |
| 966 return leftResult.equalEqual(_typeProvider, node, rightResult); |
| 967 } else if (operatorType == TokenType.GT) { |
| 968 return leftResult.greaterThan(_typeProvider, node, rightResult); |
| 969 } else if (operatorType == TokenType.GT_EQ) { |
| 970 return leftResult.greaterThanOrEqual(_typeProvider, node, rightResult); |
| 971 } else if (operatorType == TokenType.GT_GT) { |
| 972 return leftResult.shiftRight(_typeProvider, node, rightResult); |
| 973 } else if (operatorType == TokenType.LT) { |
| 974 return leftResult.lessThan(_typeProvider, node, rightResult); |
| 975 } else if (operatorType == TokenType.LT_EQ) { |
| 976 return leftResult.lessThanOrEqual(_typeProvider, node, rightResult); |
| 977 } else if (operatorType == TokenType.LT_LT) { |
| 978 return leftResult.shiftLeft(_typeProvider, node, rightResult); |
| 979 } else if (operatorType == TokenType.MINUS) { |
| 980 return leftResult.minus(_typeProvider, node, rightResult); |
| 981 } else if (operatorType == TokenType.PERCENT) { |
| 982 return leftResult.remainder(_typeProvider, node, rightResult); |
| 983 } else if (operatorType == TokenType.PLUS) { |
| 984 return leftResult.add(_typeProvider, node, rightResult); |
| 985 } else if (operatorType == TokenType.STAR) { |
| 986 return leftResult.times(_typeProvider, node, rightResult); |
| 987 } else if (operatorType == TokenType.SLASH) { |
| 988 return leftResult.divide(_typeProvider, node, rightResult); |
| 989 } else if (operatorType == TokenType.TILDE_SLASH) { |
| 990 return leftResult.integerDivide(_typeProvider, node, rightResult); |
| 991 } else { |
| 992 // TODO(brianwilkerson) Figure out which error to report. |
| 993 return _error(node, null); |
| 994 } |
| 995 break; |
| 996 } |
| 997 } |
| 998 |
| 999 @override |
| 1000 EvaluationResultImpl visitBooleanLiteral(BooleanLiteral node) => _valid(_typeP
rovider.boolType, BoolState.from(node.value)); |
| 1001 |
| 1002 @override |
| 1003 EvaluationResultImpl visitConditionalExpression(ConditionalExpression node) { |
| 1004 Expression condition = node.condition; |
| 1005 EvaluationResultImpl conditionResult = condition.accept(this); |
| 1006 EvaluationResultImpl thenResult = node.thenExpression.accept(this); |
| 1007 EvaluationResultImpl elseResult = node.elseExpression.accept(this); |
| 1008 if (conditionResult is ErrorResult) { |
| 1009 return _union(_union(conditionResult as ErrorResult, thenResult), elseResu
lt); |
| 1010 } else if (!(conditionResult as ValidResult).isBool) { |
| 1011 return new ErrorResult.con1(condition, CompileTimeErrorCode.CONST_EVAL_TYP
E_BOOL); |
| 1012 } else if (thenResult is ErrorResult) { |
| 1013 return _union(thenResult, elseResult); |
| 1014 } else if (elseResult is ErrorResult) { |
| 1015 return elseResult; |
| 1016 } |
| 1017 conditionResult = conditionResult.applyBooleanConversion(_typeProvider, cond
ition); |
| 1018 if (conditionResult is ErrorResult) { |
| 1019 return conditionResult; |
| 1020 } |
| 1021 ValidResult validResult = conditionResult as ValidResult; |
| 1022 if (validResult.isTrue) { |
| 1023 return thenResult; |
| 1024 } else if (validResult.isFalse) { |
| 1025 return elseResult; |
| 1026 } |
| 1027 InterfaceType thenType = (thenResult as ValidResult).value.type; |
| 1028 InterfaceType elseType = (elseResult as ValidResult).value.type; |
| 1029 return _validWithUnknownValue(thenType.getLeastUpperBound(elseType) as Inter
faceType); |
| 1030 } |
| 1031 |
| 1032 @override |
| 1033 EvaluationResultImpl visitDoubleLiteral(DoubleLiteral node) => _valid(_typePro
vider.doubleType, new DoubleState(node.value)); |
| 1034 |
| 1035 @override |
| 1036 EvaluationResultImpl visitInstanceCreationExpression(InstanceCreationExpressio
n node) { |
| 1037 if (!node.isConst) { |
| 1038 // TODO(brianwilkerson) Figure out which error to report. |
| 1039 return _error(node, null); |
| 1040 } |
| 1041 beforeGetEvaluationResult(node); |
| 1042 EvaluationResultImpl result = node.evaluationResult; |
| 1043 if (result != null) { |
| 1044 return result; |
| 1045 } |
| 1046 // TODO(brianwilkerson) Figure out which error to report. |
| 1047 return _error(node, null); |
| 1048 } |
| 1049 |
| 1050 @override |
| 1051 EvaluationResultImpl visitIntegerLiteral(IntegerLiteral node) => _valid(_typeP
rovider.intType, new IntState(node.value)); |
| 1052 |
| 1053 @override |
| 1054 EvaluationResultImpl visitInterpolationExpression(InterpolationExpression node
) { |
| 1055 EvaluationResultImpl result = node.expression.accept(this); |
| 1056 if (result is ValidResult && !result.isBoolNumStringOrNull) { |
| 1057 return _error(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING); |
| 1058 } |
| 1059 return result.performToString(_typeProvider, node); |
| 1060 } |
| 1061 |
| 1062 @override |
| 1063 EvaluationResultImpl visitInterpolationString(InterpolationString node) => _va
lid(_typeProvider.stringType, new StringState(node.value)); |
| 1064 |
| 1065 @override |
| 1066 EvaluationResultImpl visitListLiteral(ListLiteral node) { |
| 1067 if (node.constKeyword == null) { |
| 1068 return new ErrorResult.con1(node, CompileTimeErrorCode.MISSING_CONST_IN_LI
ST_LITERAL); |
| 1069 } |
| 1070 ErrorResult result = null; |
| 1071 List<DartObjectImpl> elements = new List<DartObjectImpl>(); |
| 1072 for (Expression element in node.elements) { |
| 1073 EvaluationResultImpl elementResult = element.accept(this); |
| 1074 result = _union(result, elementResult); |
| 1075 if (elementResult is ValidResult) { |
| 1076 elements.add(elementResult.value); |
| 1077 } |
| 1078 } |
| 1079 if (result != null) { |
| 1080 return result; |
| 1081 } |
| 1082 return _valid(_typeProvider.listType, new ListState(new List.from(elements))
); |
| 1083 } |
| 1084 |
| 1085 @override |
| 1086 EvaluationResultImpl visitMapLiteral(MapLiteral node) { |
| 1087 if (node.constKeyword == null) { |
| 1088 return new ErrorResult.con1(node, CompileTimeErrorCode.MISSING_CONST_IN_MA
P_LITERAL); |
| 1089 } |
| 1090 ErrorResult result = null; |
| 1091 HashMap<DartObjectImpl, DartObjectImpl> map = new HashMap<DartObjectImpl, Da
rtObjectImpl>(); |
| 1092 for (MapLiteralEntry entry in node.entries) { |
| 1093 EvaluationResultImpl keyResult = entry.key.accept(this); |
| 1094 EvaluationResultImpl valueResult = entry.value.accept(this); |
| 1095 result = _union(result, keyResult); |
| 1096 result = _union(result, valueResult); |
| 1097 if (keyResult is ValidResult && valueResult is ValidResult) { |
| 1098 map[keyResult.value] = valueResult.value; |
| 1099 } |
| 1100 } |
| 1101 if (result != null) { |
| 1102 return result; |
| 1103 } |
| 1104 return _valid(_typeProvider.mapType, new MapState(map)); |
| 1105 } |
| 1106 |
| 1107 @override |
| 1108 EvaluationResultImpl visitMethodInvocation(MethodInvocation node) { |
| 1109 Element element = node.methodName.staticElement; |
| 1110 if (element is FunctionElement) { |
| 1111 FunctionElement function = element; |
| 1112 if (function.name == "identical") { |
| 1113 NodeList<Expression> arguments = node.argumentList.arguments; |
| 1114 if (arguments.length == 2) { |
| 1115 Element enclosingElement = function.enclosingElement; |
| 1116 if (enclosingElement is CompilationUnitElement) { |
| 1117 LibraryElement library = enclosingElement.library; |
| 1118 if (library.isDartCore) { |
| 1119 EvaluationResultImpl leftArgument = arguments[0].accept(this); |
| 1120 EvaluationResultImpl rightArgument = arguments[1].accept(this); |
| 1121 return leftArgument.equalEqual(_typeProvider, node, rightArgument)
; |
| 1122 } |
| 1123 } |
| 1124 } |
| 1125 } |
| 1126 } |
| 1127 // TODO(brianwilkerson) Figure out which error to report. |
| 1128 return _error(node, null); |
| 1129 } |
| 1130 |
| 1131 @override |
| 1132 EvaluationResultImpl visitNamedExpression(NamedExpression node) => node.expres
sion.accept(this); |
| 1133 |
| 1134 @override |
| 1135 EvaluationResultImpl visitNode(AstNode node) => _error(node, null); |
| 1136 |
| 1137 @override |
| 1138 EvaluationResultImpl visitNullLiteral(NullLiteral node) => new ValidResult(nul
l2); |
| 1139 |
| 1140 @override |
| 1141 EvaluationResultImpl visitParenthesizedExpression(ParenthesizedExpression node
) => node.expression.accept(this); |
| 1142 |
| 1143 @override |
| 1144 EvaluationResultImpl visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 1145 // validate prefix |
| 1146 SimpleIdentifier prefixNode = node.prefix; |
| 1147 Element prefixElement = prefixNode.staticElement; |
| 1148 if (prefixElement is! PrefixElement) { |
| 1149 EvaluationResultImpl prefixResult = prefixNode.accept(this); |
| 1150 if (prefixResult is! ValidResult) { |
| 1151 return _error(node, null); |
| 1152 } |
| 1153 } |
| 1154 // validate prefixed identifier |
| 1155 return _getConstantValue(node, node.staticElement); |
| 1156 } |
| 1157 |
| 1158 @override |
| 1159 EvaluationResultImpl visitPrefixExpression(PrefixExpression node) { |
| 1160 EvaluationResultImpl operand = node.operand.accept(this); |
| 1161 if (operand is ValidResult && operand.isNull) { |
| 1162 return _error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION); |
| 1163 } |
| 1164 while (true) { |
| 1165 if (node.operator.type == TokenType.BANG) { |
| 1166 return operand.logicalNot(_typeProvider, node); |
| 1167 } else if (node.operator.type == TokenType.TILDE) { |
| 1168 return operand.bitNot(_typeProvider, node); |
| 1169 } else if (node.operator.type == TokenType.MINUS) { |
| 1170 return operand.negated(_typeProvider, node); |
| 1171 } else { |
| 1172 // TODO(brianwilkerson) Figure out which error to report. |
| 1173 return _error(node, null); |
| 1174 } |
| 1175 break; |
| 1176 } |
| 1177 } |
| 1178 |
| 1179 @override |
| 1180 EvaluationResultImpl visitPropertyAccess(PropertyAccess node) => _getConstantV
alue(node, node.propertyName.staticElement); |
| 1181 |
| 1182 @override |
| 1183 EvaluationResultImpl visitSimpleIdentifier(SimpleIdentifier node) { |
| 1184 if (_lexicalEnvironment != null && _lexicalEnvironment.containsKey(node.name
)) { |
| 1185 return new ValidResult(_lexicalEnvironment[node.name]); |
| 1186 } |
| 1187 return _getConstantValue(node, node.staticElement); |
| 1188 } |
| 1189 |
| 1190 @override |
| 1191 EvaluationResultImpl visitSimpleStringLiteral(SimpleStringLiteral node) => _va
lid(_typeProvider.stringType, new StringState(node.value)); |
| 1192 |
| 1193 @override |
| 1194 EvaluationResultImpl visitStringInterpolation(StringInterpolation node) { |
| 1195 EvaluationResultImpl result = null; |
| 1196 for (InterpolationElement element in node.elements) { |
| 1197 if (result == null) { |
| 1198 result = element.accept(this); |
| 1199 } else { |
| 1200 result = result.concatenate(_typeProvider, node, element.accept(this)); |
| 1201 } |
| 1202 } |
| 1203 return result; |
| 1204 } |
| 1205 |
| 1206 @override |
| 1207 EvaluationResultImpl visitSymbolLiteral(SymbolLiteral node) { |
| 1208 JavaStringBuilder builder = new JavaStringBuilder(); |
| 1209 List<Token> components = node.components; |
| 1210 for (int i = 0; i < components.length; i++) { |
| 1211 if (i > 0) { |
| 1212 builder.appendChar(0x2E); |
| 1213 } |
| 1214 builder.append(components[i].lexeme); |
| 1215 } |
| 1216 return _valid(_typeProvider.symbolType, new SymbolState(builder.toString()))
; |
| 1217 } |
| 1218 |
| 1219 /** |
| 1220 * This method is called just before retrieving an evaluation result from an A
ST node. Unit tests |
| 1221 * will override it to introduce additional error checking. |
| 1222 */ |
| 1223 void beforeGetEvaluationResult(AstNode node) { |
| 1224 } |
| 1225 |
| 1226 /** |
| 1227 * Return an object representing the value 'null'. |
| 1228 * |
| 1229 * @return an object representing the value 'null' |
| 1230 */ |
| 1231 DartObjectImpl get null2 { |
| 1232 if (_nullObject == null) { |
| 1233 _nullObject = new DartObjectImpl(_typeProvider.nullType, NullState.NULL_ST
ATE); |
| 1234 } |
| 1235 return _nullObject; |
| 1236 } |
| 1237 |
| 1238 ValidResult _valid(InterfaceType type, InstanceState state) => new ValidResult
(new DartObjectImpl(type, state)); |
| 1239 |
| 1240 ValidResult _validWithUnknownValue(InterfaceType type) { |
| 1241 if (type.element.library.isDartCore) { |
| 1242 String typeName = type.name; |
| 1243 if (typeName == "bool") { |
| 1244 return _valid(type, BoolState.UNKNOWN_VALUE); |
| 1245 } else if (typeName == "double") { |
| 1246 return _valid(type, DoubleState.UNKNOWN_VALUE); |
| 1247 } else if (typeName == "int") { |
| 1248 return _valid(type, IntState.UNKNOWN_VALUE); |
| 1249 } else if (typeName == "String") { |
| 1250 return _valid(type, StringState.UNKNOWN_VALUE); |
| 1251 } |
| 1252 } |
| 1253 return _valid(type, GenericState.UNKNOWN_VALUE); |
| 1254 } |
| 1255 |
| 1256 /** |
| 1257 * Return the value of the given expression, or a representation of 'null' if
the expression |
| 1258 * cannot be evaluated. |
| 1259 * |
| 1260 * @param expression the expression whose value is to be returned |
| 1261 * @return the value of the given expression |
| 1262 */ |
| 1263 DartObjectImpl _valueOf(Expression expression) { |
| 1264 EvaluationResultImpl expressionValue = expression.accept(this); |
| 1265 if (expressionValue is ValidResult) { |
| 1266 return expressionValue.value; |
| 1267 } |
| 1268 return null2; |
| 1269 } |
| 1270 |
| 1271 /** |
| 1272 * Return a result object representing an error associated with the given node
. |
| 1273 * |
| 1274 * @param node the AST node associated with the error |
| 1275 * @param code the error code indicating the nature of the error |
| 1276 * @return a result object representing an error associated with the given nod
e |
| 1277 */ |
| 1278 ErrorResult _error(AstNode node, ErrorCode code) => new ErrorResult.con1(node,
code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code); |
| 1279 |
| 1280 /** |
| 1281 * Return the constant value of the static constant represented by the given e
lement. |
| 1282 * |
| 1283 * @param node the node to be used if an error needs to be reported |
| 1284 * @param element the element whose value is to be returned |
| 1285 * @return the constant value of the static constant |
| 1286 */ |
| 1287 EvaluationResultImpl _getConstantValue(AstNode node, Element element) { |
| 1288 if (element is PropertyAccessorElement) { |
| 1289 element = (element as PropertyAccessorElement).variable; |
| 1290 } |
| 1291 if (element is VariableElementImpl) { |
| 1292 VariableElementImpl variableElementImpl = element; |
| 1293 beforeGetEvaluationResult(node); |
| 1294 EvaluationResultImpl value = variableElementImpl.evaluationResult; |
| 1295 if (variableElementImpl.isConst && value != null) { |
| 1296 return value; |
| 1297 } |
| 1298 } else if (element is ExecutableElement) { |
| 1299 ExecutableElement function = element; |
| 1300 if (function.isStatic) { |
| 1301 return _valid(_typeProvider.functionType, new FunctionState(function)); |
| 1302 } |
| 1303 } else if (element is ClassElement || element is FunctionTypeAliasElement) { |
| 1304 return _valid(_typeProvider.typeType, new TypeState(element)); |
| 1305 } |
| 1306 // TODO(brianwilkerson) Figure out which error to report. |
| 1307 return _error(node, null); |
| 1308 } |
| 1309 |
| 1310 /** |
| 1311 * Return the union of the errors encoded in the given results. |
| 1312 * |
| 1313 * @param leftResult the first set of errors, or `null` if there was no previo
us collection |
| 1314 * of errors |
| 1315 * @param rightResult the errors to be added to the collection, or a valid res
ult if there are no |
| 1316 * errors to be added |
| 1317 * @return the union of the errors encoded in the given results |
| 1318 */ |
| 1319 ErrorResult _union(ErrorResult leftResult, EvaluationResultImpl rightResult) { |
| 1320 if (rightResult is ErrorResult) { |
| 1321 if (leftResult != null) { |
| 1322 return new ErrorResult.con2(leftResult, rightResult); |
| 1323 } else { |
| 1324 return rightResult; |
| 1325 } |
| 1326 } |
| 1327 return leftResult; |
| 1328 } |
| 1329 } |
| 1330 |
| 1331 /** |
| 1332 * The interface `DartObject` defines the behavior of objects that represent the
state of a |
| 1333 * Dart object. |
| 1334 */ |
| 1335 abstract class DartObject { |
| 1336 /** |
| 1337 * Return the boolean value of this object, or `null` if either the value of t
his object is |
| 1338 * not known or this object is not of type 'bool'. |
| 1339 * |
| 1340 * @return the boolean value of this object |
| 1341 */ |
| 1342 bool get boolValue; |
| 1343 |
| 1344 /** |
| 1345 * Return the floating point value of this object, or `null` if either the val
ue of this |
| 1346 * object is not known or this object is not of type 'double'. |
| 1347 * |
| 1348 * @return the floating point value of this object |
| 1349 */ |
| 1350 double get doubleValue; |
| 1351 |
| 1352 /** |
| 1353 * Return the integer value of this object, or `null` if either the value of t
his object is |
| 1354 * not known or this object is not of type 'int'. |
| 1355 * |
| 1356 * @return the integer value of this object |
| 1357 */ |
| 1358 int get intValue; |
| 1359 |
| 1360 /** |
| 1361 * Return the string value of this object, or `null` if either the value of th
is object is |
| 1362 * not known or this object is not of type 'String'. |
| 1363 * |
| 1364 * @return the string value of this object |
| 1365 */ |
| 1366 String get stringValue; |
| 1367 |
| 1368 /** |
| 1369 * Return the run-time type of this object. |
| 1370 * |
| 1371 * @return the run-time type of this object |
| 1372 */ |
| 1373 InterfaceType get type; |
| 1374 |
| 1375 /** |
| 1376 * Return this object's value if it can be represented exactly, or `null` if e
ither the |
| 1377 * value cannot be represented exactly or if the value is `null`. Clients shou
ld use |
| 1378 * [hasExactValue] to distinguish between these two cases. |
| 1379 * |
| 1380 * @return this object's value |
| 1381 */ |
| 1382 Object get value; |
| 1383 |
| 1384 /** |
| 1385 * Return `true` if this object's value can be represented exactly. |
| 1386 * |
| 1387 * @return `true` if this object's value can be represented exactly |
| 1388 */ |
| 1389 bool get hasExactValue; |
| 1390 |
| 1391 /** |
| 1392 * Return `true` if this object represents the value 'false'. |
| 1393 * |
| 1394 * @return `true` if this object represents the value 'false' |
| 1395 */ |
| 1396 bool get isFalse; |
| 1397 |
| 1398 /** |
| 1399 * Return `true` if this object represents the value 'null'. |
| 1400 * |
| 1401 * @return `true` if this object represents the value 'null' |
| 1402 */ |
| 1403 bool get isNull; |
| 1404 |
| 1405 /** |
| 1406 * Return `true` if this object represents the value 'true'. |
| 1407 * |
| 1408 * @return `true` if this object represents the value 'true' |
| 1409 */ |
| 1410 bool get isTrue; |
| 1411 } |
| 1412 |
| 1413 /** |
| 1414 * Instances of the class `DartObjectImpl` represent an instance of a Dart class
. |
| 1415 */ |
| 1416 class DartObjectImpl implements DartObject { |
| 1417 /** |
| 1418 * The run-time type of this object. |
| 1419 */ |
| 1420 final InterfaceType type; |
| 1421 |
| 1422 /** |
| 1423 * The state of the object. |
| 1424 */ |
| 1425 final InstanceState _state; |
| 1426 |
| 1427 /** |
| 1428 * Initialize a newly created object to have the given type and state. |
| 1429 * |
| 1430 * @param type the run-time type of this object |
| 1431 * @param state the state of the object |
| 1432 */ |
| 1433 DartObjectImpl(this.type, this._state); |
| 1434 |
| 1435 /** |
| 1436 * Return the result of invoking the '+' operator on this object with the give
n argument. |
| 1437 * |
| 1438 * @param typeProvider the type provider used to find known types |
| 1439 * @param rightOperand the right-hand operand of the operation |
| 1440 * @return the result of invoking the '+' operator on this object with the giv
en argument |
| 1441 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1442 */ |
| 1443 DartObjectImpl add(TypeProvider typeProvider, DartObjectImpl rightOperand) { |
| 1444 InstanceState result = _state.add(rightOperand._state); |
| 1445 if (result is IntState) { |
| 1446 return new DartObjectImpl(typeProvider.intType, result); |
| 1447 } else if (result is DoubleState) { |
| 1448 return new DartObjectImpl(typeProvider.doubleType, result); |
| 1449 } else if (result is NumState) { |
| 1450 return new DartObjectImpl(typeProvider.numType, result); |
| 1451 } |
| 1452 // We should never get here. |
| 1453 throw new IllegalStateException("add returned a ${result.runtimeType.toStrin
g()}"); |
| 1454 } |
| 1455 |
| 1456 /** |
| 1457 * Return the result of invoking the '&' operator on this object with the give
n argument. |
| 1458 * |
| 1459 * @param typeProvider the type provider used to find known types |
| 1460 * @param rightOperand the right-hand operand of the operation |
| 1461 * @return the result of invoking the '&' operator on this object with the giv
en argument |
| 1462 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1463 */ |
| 1464 DartObjectImpl bitAnd(TypeProvider typeProvider, DartObjectImpl rightOperand)
=> new DartObjectImpl(typeProvider.intType, _state.bitAnd(rightOperand._state)); |
| 1465 |
| 1466 /** |
| 1467 * Return the result of invoking the '~' operator on this object. |
| 1468 * |
| 1469 * @param typeProvider the type provider used to find known types |
| 1470 * @return the result of invoking the '~' operator on this object |
| 1471 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1472 */ |
| 1473 DartObjectImpl bitNot(TypeProvider typeProvider) => new DartObjectImpl(typePro
vider.intType, _state.bitNot()); |
| 1474 |
| 1475 /** |
| 1476 * Return the result of invoking the '|' operator on this object with the give
n argument. |
| 1477 * |
| 1478 * @param typeProvider the type provider used to find known types |
| 1479 * @param rightOperand the right-hand operand of the operation |
| 1480 * @return the result of invoking the '|' operator on this object with the giv
en argument |
| 1481 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1482 */ |
| 1483 DartObjectImpl bitOr(TypeProvider typeProvider, DartObjectImpl rightOperand) =
> new DartObjectImpl(typeProvider.intType, _state.bitOr(rightOperand._state)); |
| 1484 |
| 1485 /** |
| 1486 * Return the result of invoking the '^' operator on this object with the give
n argument. |
| 1487 * |
| 1488 * @param typeProvider the type provider used to find known types |
| 1489 * @param rightOperand the right-hand operand of the operation |
| 1490 * @return the result of invoking the '^' operator on this object with the giv
en argument |
| 1491 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1492 */ |
| 1493 DartObjectImpl bitXor(TypeProvider typeProvider, DartObjectImpl rightOperand)
=> new DartObjectImpl(typeProvider.intType, _state.bitXor(rightOperand._state)); |
| 1494 |
| 1495 /** |
| 1496 * Return the result of invoking the ' ' operator on this object with the give
n argument. |
| 1497 * |
| 1498 * @param typeProvider the type provider used to find known types |
| 1499 * @param rightOperand the right-hand operand of the operation |
| 1500 * @return the result of invoking the ' ' operator on this object with the giv
en argument |
| 1501 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1502 */ |
| 1503 DartObjectImpl concatenate(TypeProvider typeProvider, DartObjectImpl rightOper
and) => new DartObjectImpl(typeProvider.stringType, _state.concatenate(rightOper
and._state)); |
| 1504 |
| 1505 /** |
| 1506 * Return the result of applying boolean conversion to this object. |
| 1507 * |
| 1508 * @param typeProvider the type provider used to find known types |
| 1509 * @return the result of applying boolean conversion to this object |
| 1510 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1511 */ |
| 1512 DartObjectImpl convertToBool(TypeProvider typeProvider) { |
| 1513 InterfaceType boolType = typeProvider.boolType; |
| 1514 if (identical(type, boolType)) { |
| 1515 return this; |
| 1516 } |
| 1517 return new DartObjectImpl(boolType, _state.convertToBool()); |
| 1518 } |
| 1519 |
| 1520 /** |
| 1521 * Return the result of invoking the '/' operator on this object with the give
n argument. |
| 1522 * |
| 1523 * @param typeProvider the type provider used to find known types |
| 1524 * @param rightOperand the right-hand operand of the operation |
| 1525 * @return the result of invoking the '/' operator on this object with the giv
en argument |
| 1526 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1527 */ |
| 1528 DartObjectImpl divide(TypeProvider typeProvider, DartObjectImpl rightOperand)
{ |
| 1529 InstanceState result = _state.divide(rightOperand._state); |
| 1530 if (result is IntState) { |
| 1531 return new DartObjectImpl(typeProvider.intType, result); |
| 1532 } else if (result is DoubleState) { |
| 1533 return new DartObjectImpl(typeProvider.doubleType, result); |
| 1534 } else if (result is NumState) { |
| 1535 return new DartObjectImpl(typeProvider.numType, result); |
| 1536 } |
| 1537 // We should never get here. |
| 1538 throw new IllegalStateException("divide returned a ${result.runtimeType.toSt
ring()}"); |
| 1539 } |
| 1540 |
| 1541 /** |
| 1542 * Return the result of invoking the '==' operator on this object with the giv
en argument. |
| 1543 * |
| 1544 * @param typeProvider the type provider used to find known types |
| 1545 * @param rightOperand the right-hand operand of the operation |
| 1546 * @return the result of invoking the '==' operator on this object with the gi
ven argument |
| 1547 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1548 */ |
| 1549 DartObjectImpl equalEqual(TypeProvider typeProvider, DartObjectImpl rightOpera
nd) { |
| 1550 if (type != rightOperand.type) { |
| 1551 String typeName = type.name; |
| 1552 if (!(typeName == "bool" || typeName == "double" || typeName == "int" || t
ypeName == "num" || typeName == "String" || typeName == "Null" || type.isDynamic
)) { |
| 1553 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_
NUM_STRING); |
| 1554 } |
| 1555 } |
| 1556 return new DartObjectImpl(typeProvider.boolType, _state.equalEqual(rightOper
and._state)); |
| 1557 } |
| 1558 |
| 1559 @override |
| 1560 bool operator ==(Object object) { |
| 1561 if (object is! DartObjectImpl) { |
| 1562 return false; |
| 1563 } |
| 1564 DartObjectImpl dartObject = object as DartObjectImpl; |
| 1565 return type == dartObject.type && _state == dartObject._state; |
| 1566 } |
| 1567 |
| 1568 @override |
| 1569 bool get boolValue { |
| 1570 if (_state is BoolState) { |
| 1571 return (_state as BoolState).value; |
| 1572 } |
| 1573 return null; |
| 1574 } |
| 1575 |
| 1576 @override |
| 1577 double get doubleValue { |
| 1578 if (_state is DoubleState) { |
| 1579 return (_state as DoubleState).value; |
| 1580 } |
| 1581 return null; |
| 1582 } |
| 1583 |
| 1584 HashMap<String, DartObjectImpl> get fields => _state.fields; |
| 1585 |
| 1586 @override |
| 1587 int get intValue { |
| 1588 if (_state is IntState) { |
| 1589 return (_state as IntState).value; |
| 1590 } |
| 1591 return null; |
| 1592 } |
| 1593 |
| 1594 @override |
| 1595 String get stringValue { |
| 1596 if (_state is StringState) { |
| 1597 return (_state as StringState).value; |
| 1598 } |
| 1599 return null; |
| 1600 } |
| 1601 |
| 1602 @override |
| 1603 Object get value => _state.value; |
| 1604 |
| 1605 /** |
| 1606 * Return the result of invoking the '>' operator on this object with the g
iven argument. |
| 1607 * |
| 1608 * @param typeProvider the type provider used to find known types |
| 1609 * @param rightOperand the right-hand operand of the operation |
| 1610 * @return the result of invoking the '>' operator on this object with the
given argument |
| 1611 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1612 */ |
| 1613 DartObjectImpl greaterThan(TypeProvider typeProvider, DartObjectImpl rightOper
and) => new DartObjectImpl(typeProvider.boolType, _state.greaterThan(rightOperan
d._state)); |
| 1614 |
| 1615 /** |
| 1616 * Return the result of invoking the '>=' operator on this object with the
given argument. |
| 1617 * |
| 1618 * @param typeProvider the type provider used to find known types |
| 1619 * @param rightOperand the right-hand operand of the operation |
| 1620 * @return the result of invoking the '>=' operator on this object with the
given argument |
| 1621 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1622 */ |
| 1623 DartObjectImpl greaterThanOrEqual(TypeProvider typeProvider, DartObjectImpl ri
ghtOperand) => new DartObjectImpl(typeProvider.boolType, _state.greaterThanOrEqu
al(rightOperand._state)); |
| 1624 |
| 1625 @override |
| 1626 bool get hasExactValue => _state.hasExactValue; |
| 1627 |
| 1628 @override |
| 1629 int get hashCode => ObjectUtilities.combineHashCodes(type.hashCode, _state.has
hCode); |
| 1630 |
| 1631 /** |
| 1632 * Return the result of invoking the '~/' operator on this object with the giv
en argument. |
| 1633 * |
| 1634 * @param typeProvider the type provider used to find known types |
| 1635 * @param rightOperand the right-hand operand of the operation |
| 1636 * @return the result of invoking the '~/' operator on this object with the gi
ven argument |
| 1637 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1638 */ |
| 1639 DartObjectImpl integerDivide(TypeProvider typeProvider, DartObjectImpl rightOp
erand) => new DartObjectImpl(typeProvider.intType, _state.integerDivide(rightOpe
rand._state)); |
| 1640 |
| 1641 /** |
| 1642 * Return `true` if this object represents an object whose type is 'bool'. |
| 1643 * |
| 1644 * @return `true` if this object represents a boolean value |
| 1645 */ |
| 1646 bool get isBool => _state.isBool; |
| 1647 |
| 1648 /** |
| 1649 * Return `true` if this object represents an object whose type is either 'boo
l', 'num', |
| 1650 * 'String', or 'Null'. |
| 1651 * |
| 1652 * @return `true` if this object represents either a boolean, numeric, string
or null value |
| 1653 */ |
| 1654 bool get isBoolNumStringOrNull => _state.isBoolNumStringOrNull; |
| 1655 |
| 1656 @override |
| 1657 bool get isFalse => _state is BoolState && identical((_state as BoolState).val
ue, false); |
| 1658 |
| 1659 @override |
| 1660 bool get isNull => _state is NullState; |
| 1661 |
| 1662 @override |
| 1663 bool get isTrue => _state is BoolState && identical((_state as BoolState).valu
e, true); |
| 1664 |
| 1665 /** |
| 1666 * Return true if this object represents an unknown value. |
| 1667 */ |
| 1668 bool get isUnknown => _state.isUnknown; |
| 1669 |
| 1670 /** |
| 1671 * Return `true` if this object represents an instance of a user-defined class
. |
| 1672 * |
| 1673 * @return `true` if this object represents an instance of a user-defined clas
s |
| 1674 */ |
| 1675 bool get isUserDefinedObject => _state is GenericState; |
| 1676 |
| 1677 /** |
| 1678 * Return the result of invoking the '<' operator on this object with the g
iven argument. |
| 1679 * |
| 1680 * @param typeProvider the type provider used to find known types |
| 1681 * @param rightOperand the right-hand operand of the operation |
| 1682 * @return the result of invoking the '<' operator on this object with the
given argument |
| 1683 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1684 */ |
| 1685 DartObjectImpl lessThan(TypeProvider typeProvider, DartObjectImpl rightOperand
) => new DartObjectImpl(typeProvider.boolType, _state.lessThan(rightOperand._sta
te)); |
| 1686 |
| 1687 /** |
| 1688 * Return the result of invoking the '<=' operator on this object with the
given argument. |
| 1689 * |
| 1690 * @param typeProvider the type provider used to find known types |
| 1691 * @param rightOperand the right-hand operand of the operation |
| 1692 * @return the result of invoking the '<=' operator on this object with the
given argument |
| 1693 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1694 */ |
| 1695 DartObjectImpl lessThanOrEqual(TypeProvider typeProvider, DartObjectImpl right
Operand) => new DartObjectImpl(typeProvider.boolType, _state.lessThanOrEqual(rig
htOperand._state)); |
| 1696 |
| 1697 /** |
| 1698 * Return the result of invoking the '&&' operator on this object with the giv
en argument. |
| 1699 * |
| 1700 * @param typeProvider the type provider used to find known types |
| 1701 * @param rightOperand the right-hand operand of the operation |
| 1702 * @return the result of invoking the '&&' operator on this object with the gi
ven argument |
| 1703 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1704 */ |
| 1705 DartObjectImpl logicalAnd(TypeProvider typeProvider, DartObjectImpl rightOpera
nd) => new DartObjectImpl(typeProvider.boolType, _state.logicalAnd(rightOperand.
_state)); |
| 1706 |
| 1707 /** |
| 1708 * Return the result of invoking the '!' operator on this object. |
| 1709 * |
| 1710 * @param typeProvider the type provider used to find known types |
| 1711 * @return the result of invoking the '!' operator on this object |
| 1712 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1713 */ |
| 1714 DartObjectImpl logicalNot(TypeProvider typeProvider) => new DartObjectImpl(typ
eProvider.boolType, _state.logicalNot()); |
| 1715 |
| 1716 /** |
| 1717 * Return the result of invoking the '||' operator on this object with the giv
en argument. |
| 1718 * |
| 1719 * @param typeProvider the type provider used to find known types |
| 1720 * @param rightOperand the right-hand operand of the operation |
| 1721 * @return the result of invoking the '||' operator on this object with the gi
ven argument |
| 1722 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1723 */ |
| 1724 DartObjectImpl logicalOr(TypeProvider typeProvider, DartObjectImpl rightOperan
d) => new DartObjectImpl(typeProvider.boolType, _state.logicalOr(rightOperand._s
tate)); |
| 1725 |
| 1726 /** |
| 1727 * Return the result of invoking the '-' operator on this object with the give
n argument. |
| 1728 * |
| 1729 * @param typeProvider the type provider used to find known types |
| 1730 * @param rightOperand the right-hand operand of the operation |
| 1731 * @return the result of invoking the '-' operator on this object with the giv
en argument |
| 1732 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1733 */ |
| 1734 DartObjectImpl minus(TypeProvider typeProvider, DartObjectImpl rightOperand) { |
| 1735 InstanceState result = _state.minus(rightOperand._state); |
| 1736 if (result is IntState) { |
| 1737 return new DartObjectImpl(typeProvider.intType, result); |
| 1738 } else if (result is DoubleState) { |
| 1739 return new DartObjectImpl(typeProvider.doubleType, result); |
| 1740 } else if (result is NumState) { |
| 1741 return new DartObjectImpl(typeProvider.numType, result); |
| 1742 } |
| 1743 // We should never get here. |
| 1744 throw new IllegalStateException("minus returned a ${result.runtimeType.toStr
ing()}"); |
| 1745 } |
| 1746 |
| 1747 /** |
| 1748 * Return the result of invoking the '-' operator on this object. |
| 1749 * |
| 1750 * @param typeProvider the type provider used to find known types |
| 1751 * @return the result of invoking the '-' operator on this object |
| 1752 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1753 */ |
| 1754 DartObjectImpl negated(TypeProvider typeProvider) { |
| 1755 InstanceState result = _state.negated(); |
| 1756 if (result is IntState) { |
| 1757 return new DartObjectImpl(typeProvider.intType, result); |
| 1758 } else if (result is DoubleState) { |
| 1759 return new DartObjectImpl(typeProvider.doubleType, result); |
| 1760 } else if (result is NumState) { |
| 1761 return new DartObjectImpl(typeProvider.numType, result); |
| 1762 } |
| 1763 // We should never get here. |
| 1764 throw new IllegalStateException("negated returned a ${result.runtimeType.toS
tring()}"); |
| 1765 } |
| 1766 |
| 1767 /** |
| 1768 * Return the result of invoking the '!=' operator on this object with the giv
en argument. |
| 1769 * |
| 1770 * @param typeProvider the type provider used to find known types |
| 1771 * @param rightOperand the right-hand operand of the operation |
| 1772 * @return the result of invoking the '!=' operator on this object with the gi
ven argument |
| 1773 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1774 */ |
| 1775 DartObjectImpl notEqual(TypeProvider typeProvider, DartObjectImpl rightOperand
) { |
| 1776 if (type != rightOperand.type) { |
| 1777 String typeName = type.name; |
| 1778 if (typeName != "bool" && typeName != "double" && typeName != "int" && typ
eName != "num" && typeName != "String") { |
| 1779 return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE); |
| 1780 } |
| 1781 } |
| 1782 return new DartObjectImpl(typeProvider.boolType, _state.equalEqual(rightOper
and._state).logicalNot()); |
| 1783 } |
| 1784 |
| 1785 /** |
| 1786 * Return the result of converting this object to a String. |
| 1787 * |
| 1788 * @param typeProvider the type provider used to find known types |
| 1789 * @return the result of converting this object to a String |
| 1790 * @throws EvaluationException if the object cannot be converted to a String |
| 1791 */ |
| 1792 DartObjectImpl performToString(TypeProvider typeProvider) { |
| 1793 InterfaceType stringType = typeProvider.stringType; |
| 1794 if (identical(type, stringType)) { |
| 1795 return this; |
| 1796 } |
| 1797 return new DartObjectImpl(stringType, _state.convertToString()); |
| 1798 } |
| 1799 |
| 1800 /** |
| 1801 * Return the result of invoking the '%' operator on this object with the give
n argument. |
| 1802 * |
| 1803 * @param typeProvider the type provider used to find known types |
| 1804 * @param rightOperand the right-hand operand of the operation |
| 1805 * @return the result of invoking the '%' operator on this object with the giv
en argument |
| 1806 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1807 */ |
| 1808 DartObjectImpl remainder(TypeProvider typeProvider, DartObjectImpl rightOperan
d) { |
| 1809 InstanceState result = _state.remainder(rightOperand._state); |
| 1810 if (result is IntState) { |
| 1811 return new DartObjectImpl(typeProvider.intType, result); |
| 1812 } else if (result is DoubleState) { |
| 1813 return new DartObjectImpl(typeProvider.doubleType, result); |
| 1814 } else if (result is NumState) { |
| 1815 return new DartObjectImpl(typeProvider.numType, result); |
| 1816 } |
| 1817 // We should never get here. |
| 1818 throw new IllegalStateException("remainder returned a ${result.runtimeType.t
oString()}"); |
| 1819 } |
| 1820 |
| 1821 /** |
| 1822 * Return the result of invoking the '<<' operator on this object with t
he given argument. |
| 1823 * |
| 1824 * @param typeProvider the type provider used to find known types |
| 1825 * @param rightOperand the right-hand operand of the operation |
| 1826 * @return the result of invoking the '<<' operator on this object with
the given argument |
| 1827 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1828 */ |
| 1829 DartObjectImpl shiftLeft(TypeProvider typeProvider, DartObjectImpl rightOperan
d) => new DartObjectImpl(typeProvider.intType, _state.shiftLeft(rightOperand._st
ate)); |
| 1830 |
| 1831 /** |
| 1832 * Return the result of invoking the '>>' operator on this object with t
he given argument. |
| 1833 * |
| 1834 * @param typeProvider the type provider used to find known types |
| 1835 * @param rightOperand the right-hand operand of the operation |
| 1836 * @return the result of invoking the '>>' operator on this object with
the given argument |
| 1837 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1838 */ |
| 1839 DartObjectImpl shiftRight(TypeProvider typeProvider, DartObjectImpl rightOpera
nd) => new DartObjectImpl(typeProvider.intType, _state.shiftRight(rightOperand._
state)); |
| 1840 |
| 1841 /** |
| 1842 * Return the result of invoking the '*' operator on this object with the give
n argument. |
| 1843 * |
| 1844 * @param typeProvider the type provider used to find known types |
| 1845 * @param rightOperand the right-hand operand of the operation |
| 1846 * @return the result of invoking the '*' operator on this object with the giv
en argument |
| 1847 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 1848 */ |
| 1849 DartObjectImpl times(TypeProvider typeProvider, DartObjectImpl rightOperand) { |
| 1850 InstanceState result = _state.times(rightOperand._state); |
| 1851 if (result is IntState) { |
| 1852 return new DartObjectImpl(typeProvider.intType, result); |
| 1853 } else if (result is DoubleState) { |
| 1854 return new DartObjectImpl(typeProvider.doubleType, result); |
| 1855 } else if (result is NumState) { |
| 1856 return new DartObjectImpl(typeProvider.numType, result); |
| 1857 } |
| 1858 // We should never get here. |
| 1859 throw new IllegalStateException("times returned a ${result.runtimeType.toStr
ing()}"); |
| 1860 } |
| 1861 |
| 1862 @override |
| 1863 String toString() => "${type.displayName} (${_state.toString()})"; |
| 1864 } |
| 1865 |
| 1866 /** |
| 1867 * Instances of the class `DeclaredVariables` provide access to the values of va
riables that |
| 1868 * have been defined on the command line using the `-D` option. |
| 1869 */ |
| 1870 class DeclaredVariables { |
| 1871 /** |
| 1872 * A table mapping the names of declared variables to their values. |
| 1873 */ |
| 1874 HashMap<String, String> _declaredVariables = new HashMap<String, String>(); |
| 1875 |
| 1876 /** |
| 1877 * Define a variable with the given name to have the given value. |
| 1878 * |
| 1879 * @param variableName the name of the variable being defined |
| 1880 * @param value the value of the variable |
| 1881 */ |
| 1882 void define(String variableName, String value) { |
| 1883 _declaredVariables[variableName] = value; |
| 1884 } |
| 1885 |
| 1886 /** |
| 1887 * Return the value of the variable with the given name interpreted as a boole
an value. If the |
| 1888 * variable is not defined (or [variableName] is null), a DartObject represent
ing "unknown" |
| 1889 * is returned. If the value can't be parsed as a boolean, a DartObject repres
enting null is |
| 1890 * returned. |
| 1891 * |
| 1892 * @param typeProvider the type provider used to find the type 'bool' |
| 1893 * @param variableName the name of the variable whose value is to be returned |
| 1894 */ |
| 1895 DartObject getBool(TypeProvider typeProvider, String variableName) { |
| 1896 String value = _declaredVariables[variableName]; |
| 1897 if (value == null) { |
| 1898 return new DartObjectImpl(typeProvider.boolType, BoolState.UNKNOWN_VALUE); |
| 1899 } |
| 1900 if (value == "true") { |
| 1901 return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE); |
| 1902 } else if (value == "false") { |
| 1903 return new DartObjectImpl(typeProvider.boolType, BoolState.FALSE_STATE); |
| 1904 } |
| 1905 return new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE); |
| 1906 } |
| 1907 |
| 1908 /** |
| 1909 * Return the value of the variable with the given name interpreted as an inte
ger value. If the |
| 1910 * variable is not defined (or [variableName] is null), a DartObject represent
ing "unknown" |
| 1911 * is returned. If the value can't be parsed as an integer, a DartObject repre
senting null is |
| 1912 * returned. |
| 1913 * |
| 1914 * @param typeProvider the type provider used to find the type 'int' |
| 1915 * @param variableName the name of the variable whose value is to be returned |
| 1916 */ |
| 1917 DartObject getInt(TypeProvider typeProvider, String variableName) { |
| 1918 String value = _declaredVariables[variableName]; |
| 1919 if (value == null) { |
| 1920 return new DartObjectImpl(typeProvider.intType, IntState.UNKNOWN_VALUE); |
| 1921 } |
| 1922 int bigInteger; |
| 1923 try { |
| 1924 bigInteger = int.parse(value); |
| 1925 } on FormatException catch (exception) { |
| 1926 return new DartObjectImpl(typeProvider.nullType, NullState.NULL_STATE); |
| 1927 } |
| 1928 return new DartObjectImpl(typeProvider.intType, new IntState(bigInteger)); |
| 1929 } |
| 1930 |
| 1931 /** |
| 1932 * Return the value of the variable with the given name interpreted as a Strin
g value, or |
| 1933 * `null` if the variable is not defined. Return the value of the variable wit
h the given |
| 1934 * name interpreted as a String value. If the variable is not defined (or [var
iableName] is |
| 1935 * null), a DartObject representing "unknown" is returned. |
| 1936 * |
| 1937 * @param typeProvider the type provider used to find the type 'String' |
| 1938 * @param variableName the name of the variable whose value is to be returned |
| 1939 */ |
| 1940 DartObject getString(TypeProvider typeProvider, String variableName) { |
| 1941 String value = _declaredVariables[variableName]; |
| 1942 if (value == null) { |
| 1943 return new DartObjectImpl(typeProvider.intType, IntState.UNKNOWN_VALUE); |
| 1944 } |
| 1945 return new DartObjectImpl(typeProvider.stringType, new StringState(value)); |
| 1946 } |
| 1947 } |
| 1948 |
| 1949 /** |
| 1950 * Instances of the class `DoubleState` represent the state of an object represe
nting a |
| 1951 * double. |
| 1952 */ |
| 1953 class DoubleState extends NumState { |
| 1954 /** |
| 1955 * The value of this instance. |
| 1956 */ |
| 1957 final double value; |
| 1958 |
| 1959 /** |
| 1960 * A state that can be used to represent a double whose value is not known. |
| 1961 */ |
| 1962 static DoubleState UNKNOWN_VALUE = new DoubleState(null); |
| 1963 |
| 1964 /** |
| 1965 * Initialize a newly created state to represent a double with the given value
. |
| 1966 * |
| 1967 * @param value the value of this instance |
| 1968 */ |
| 1969 DoubleState(this.value); |
| 1970 |
| 1971 @override |
| 1972 NumState add(InstanceState rightOperand) { |
| 1973 assertNumOrNull(rightOperand); |
| 1974 if (value == null) { |
| 1975 return UNKNOWN_VALUE; |
| 1976 } |
| 1977 if (rightOperand is IntState) { |
| 1978 int rightValue = rightOperand.value; |
| 1979 if (rightValue == null) { |
| 1980 return UNKNOWN_VALUE; |
| 1981 } |
| 1982 return new DoubleState(value + rightValue.toDouble()); |
| 1983 } else if (rightOperand is DoubleState) { |
| 1984 double rightValue = rightOperand.value; |
| 1985 if (rightValue == null) { |
| 1986 return UNKNOWN_VALUE; |
| 1987 } |
| 1988 return new DoubleState(value + rightValue); |
| 1989 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 1990 return UNKNOWN_VALUE; |
| 1991 } |
| 1992 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 1993 } |
| 1994 |
| 1995 @override |
| 1996 StringState convertToString() { |
| 1997 if (value == null) { |
| 1998 return StringState.UNKNOWN_VALUE; |
| 1999 } |
| 2000 return new StringState(value.toString()); |
| 2001 } |
| 2002 |
| 2003 @override |
| 2004 NumState divide(InstanceState rightOperand) { |
| 2005 assertNumOrNull(rightOperand); |
| 2006 if (value == null) { |
| 2007 return UNKNOWN_VALUE; |
| 2008 } |
| 2009 if (rightOperand is IntState) { |
| 2010 int rightValue = rightOperand.value; |
| 2011 if (rightValue == null) { |
| 2012 return UNKNOWN_VALUE; |
| 2013 } |
| 2014 return new DoubleState(value / rightValue.toDouble()); |
| 2015 } else if (rightOperand is DoubleState) { |
| 2016 double rightValue = rightOperand.value; |
| 2017 if (rightValue == null) { |
| 2018 return UNKNOWN_VALUE; |
| 2019 } |
| 2020 return new DoubleState(value / rightValue); |
| 2021 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 2022 return UNKNOWN_VALUE; |
| 2023 } |
| 2024 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 2025 } |
| 2026 |
| 2027 @override |
| 2028 BoolState equalEqual(InstanceState rightOperand) { |
| 2029 assertBoolNumStringOrNull(rightOperand); |
| 2030 if (value == null) { |
| 2031 return BoolState.UNKNOWN_VALUE; |
| 2032 } |
| 2033 if (rightOperand is DoubleState) { |
| 2034 double rightValue = rightOperand.value; |
| 2035 if (rightValue == null) { |
| 2036 return BoolState.UNKNOWN_VALUE; |
| 2037 } |
| 2038 return BoolState.from(value == rightValue); |
| 2039 } else if (rightOperand is IntState) { |
| 2040 int rightValue = rightOperand.value; |
| 2041 if (rightValue == null) { |
| 2042 return BoolState.UNKNOWN_VALUE; |
| 2043 } |
| 2044 return BoolState.from(value == rightValue.toDouble()); |
| 2045 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 2046 return BoolState.UNKNOWN_VALUE; |
| 2047 } |
| 2048 return BoolState.FALSE_STATE; |
| 2049 } |
| 2050 |
| 2051 @override |
| 2052 bool operator ==(Object object) => object is DoubleState && (value == object.v
alue); |
| 2053 |
| 2054 @override |
| 2055 String get typeName => "double"; |
| 2056 |
| 2057 @override |
| 2058 BoolState greaterThan(InstanceState rightOperand) { |
| 2059 assertNumOrNull(rightOperand); |
| 2060 if (value == null) { |
| 2061 return BoolState.UNKNOWN_VALUE; |
| 2062 } |
| 2063 if (rightOperand is IntState) { |
| 2064 int rightValue = rightOperand.value; |
| 2065 if (rightValue == null) { |
| 2066 return BoolState.UNKNOWN_VALUE; |
| 2067 } |
| 2068 return BoolState.from(value > rightValue.toDouble()); |
| 2069 } else if (rightOperand is DoubleState) { |
| 2070 double rightValue = rightOperand.value; |
| 2071 if (rightValue == null) { |
| 2072 return BoolState.UNKNOWN_VALUE; |
| 2073 } |
| 2074 return BoolState.from(value > rightValue); |
| 2075 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 2076 return BoolState.UNKNOWN_VALUE; |
| 2077 } |
| 2078 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 2079 } |
| 2080 |
| 2081 @override |
| 2082 BoolState greaterThanOrEqual(InstanceState rightOperand) { |
| 2083 assertNumOrNull(rightOperand); |
| 2084 if (value == null) { |
| 2085 return BoolState.UNKNOWN_VALUE; |
| 2086 } |
| 2087 if (rightOperand is IntState) { |
| 2088 int rightValue = rightOperand.value; |
| 2089 if (rightValue == null) { |
| 2090 return BoolState.UNKNOWN_VALUE; |
| 2091 } |
| 2092 return BoolState.from(value >= rightValue.toDouble()); |
| 2093 } else if (rightOperand is DoubleState) { |
| 2094 double rightValue = rightOperand.value; |
| 2095 if (rightValue == null) { |
| 2096 return BoolState.UNKNOWN_VALUE; |
| 2097 } |
| 2098 return BoolState.from(value >= rightValue); |
| 2099 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 2100 return BoolState.UNKNOWN_VALUE; |
| 2101 } |
| 2102 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 2103 } |
| 2104 |
| 2105 @override |
| 2106 bool get hasExactValue => true; |
| 2107 |
| 2108 @override |
| 2109 int get hashCode => value == null ? 0 : value.hashCode; |
| 2110 |
| 2111 @override |
| 2112 IntState integerDivide(InstanceState rightOperand) { |
| 2113 assertNumOrNull(rightOperand); |
| 2114 if (value == null) { |
| 2115 return IntState.UNKNOWN_VALUE; |
| 2116 } |
| 2117 if (rightOperand is IntState) { |
| 2118 int rightValue = rightOperand.value; |
| 2119 if (rightValue == null) { |
| 2120 return IntState.UNKNOWN_VALUE; |
| 2121 } |
| 2122 double result = value / rightValue.toDouble(); |
| 2123 return new IntState(result.toInt()); |
| 2124 } else if (rightOperand is DoubleState) { |
| 2125 double rightValue = rightOperand.value; |
| 2126 if (rightValue == null) { |
| 2127 return IntState.UNKNOWN_VALUE; |
| 2128 } |
| 2129 double result = value / rightValue; |
| 2130 return new IntState(result.toInt()); |
| 2131 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 2132 return IntState.UNKNOWN_VALUE; |
| 2133 } |
| 2134 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 2135 } |
| 2136 |
| 2137 @override |
| 2138 bool get isBoolNumStringOrNull => true; |
| 2139 |
| 2140 @override |
| 2141 bool get isUnknown => value == null; |
| 2142 |
| 2143 @override |
| 2144 BoolState lessThan(InstanceState rightOperand) { |
| 2145 assertNumOrNull(rightOperand); |
| 2146 if (value == null) { |
| 2147 return BoolState.UNKNOWN_VALUE; |
| 2148 } |
| 2149 if (rightOperand is IntState) { |
| 2150 int rightValue = rightOperand.value; |
| 2151 if (rightValue == null) { |
| 2152 return BoolState.UNKNOWN_VALUE; |
| 2153 } |
| 2154 return BoolState.from(value < rightValue.toDouble()); |
| 2155 } else if (rightOperand is DoubleState) { |
| 2156 double rightValue = rightOperand.value; |
| 2157 if (rightValue == null) { |
| 2158 return BoolState.UNKNOWN_VALUE; |
| 2159 } |
| 2160 return BoolState.from(value < rightValue); |
| 2161 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 2162 return BoolState.UNKNOWN_VALUE; |
| 2163 } |
| 2164 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 2165 } |
| 2166 |
| 2167 @override |
| 2168 BoolState lessThanOrEqual(InstanceState rightOperand) { |
| 2169 assertNumOrNull(rightOperand); |
| 2170 if (value == null) { |
| 2171 return BoolState.UNKNOWN_VALUE; |
| 2172 } |
| 2173 if (rightOperand is IntState) { |
| 2174 int rightValue = rightOperand.value; |
| 2175 if (rightValue == null) { |
| 2176 return BoolState.UNKNOWN_VALUE; |
| 2177 } |
| 2178 return BoolState.from(value <= rightValue.toDouble()); |
| 2179 } else if (rightOperand is DoubleState) { |
| 2180 double rightValue = rightOperand.value; |
| 2181 if (rightValue == null) { |
| 2182 return BoolState.UNKNOWN_VALUE; |
| 2183 } |
| 2184 return BoolState.from(value <= rightValue); |
| 2185 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 2186 return BoolState.UNKNOWN_VALUE; |
| 2187 } |
| 2188 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 2189 } |
| 2190 |
| 2191 @override |
| 2192 NumState minus(InstanceState rightOperand) { |
| 2193 assertNumOrNull(rightOperand); |
| 2194 if (value == null) { |
| 2195 return UNKNOWN_VALUE; |
| 2196 } |
| 2197 if (rightOperand is IntState) { |
| 2198 int rightValue = rightOperand.value; |
| 2199 if (rightValue == null) { |
| 2200 return UNKNOWN_VALUE; |
| 2201 } |
| 2202 return new DoubleState(value - rightValue.toDouble()); |
| 2203 } else if (rightOperand is DoubleState) { |
| 2204 double rightValue = rightOperand.value; |
| 2205 if (rightValue == null) { |
| 2206 return UNKNOWN_VALUE; |
| 2207 } |
| 2208 return new DoubleState(value - rightValue); |
| 2209 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 2210 return UNKNOWN_VALUE; |
| 2211 } |
| 2212 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 2213 } |
| 2214 |
| 2215 @override |
| 2216 NumState negated() { |
| 2217 if (value == null) { |
| 2218 return UNKNOWN_VALUE; |
| 2219 } |
| 2220 return new DoubleState(-(value)); |
| 2221 } |
| 2222 |
| 2223 @override |
| 2224 NumState remainder(InstanceState rightOperand) { |
| 2225 assertNumOrNull(rightOperand); |
| 2226 if (value == null) { |
| 2227 return UNKNOWN_VALUE; |
| 2228 } |
| 2229 if (rightOperand is IntState) { |
| 2230 int rightValue = rightOperand.value; |
| 2231 if (rightValue == null) { |
| 2232 return UNKNOWN_VALUE; |
| 2233 } |
| 2234 return new DoubleState(value % rightValue.toDouble()); |
| 2235 } else if (rightOperand is DoubleState) { |
| 2236 double rightValue = rightOperand.value; |
| 2237 if (rightValue == null) { |
| 2238 return UNKNOWN_VALUE; |
| 2239 } |
| 2240 return new DoubleState(value % rightValue); |
| 2241 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 2242 return UNKNOWN_VALUE; |
| 2243 } |
| 2244 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 2245 } |
| 2246 |
| 2247 @override |
| 2248 NumState times(InstanceState rightOperand) { |
| 2249 assertNumOrNull(rightOperand); |
| 2250 if (value == null) { |
| 2251 return UNKNOWN_VALUE; |
| 2252 } |
| 2253 if (rightOperand is IntState) { |
| 2254 int rightValue = rightOperand.value; |
| 2255 if (rightValue == null) { |
| 2256 return UNKNOWN_VALUE; |
| 2257 } |
| 2258 return new DoubleState(value * rightValue.toDouble()); |
| 2259 } else if (rightOperand is DoubleState) { |
| 2260 double rightValue = rightOperand.value; |
| 2261 if (rightValue == null) { |
| 2262 return UNKNOWN_VALUE; |
| 2263 } |
| 2264 return new DoubleState(value * rightValue); |
| 2265 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 2266 return UNKNOWN_VALUE; |
| 2267 } |
| 2268 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 2269 } |
| 2270 |
| 2271 @override |
| 2272 String toString() => value == null ? "-unknown-" : value.toString(); |
| 2273 } |
| 2274 |
| 2275 /** |
| 2276 * Instances of the class `DynamicState` represent the state of an object repres
enting a Dart |
| 2277 * object for which there is no type information. |
| 2278 */ |
| 2279 class DynamicState extends InstanceState { |
| 2280 /** |
| 2281 * The unique instance of this class. |
| 2282 */ |
| 2283 static DynamicState DYNAMIC_STATE = new DynamicState(); |
| 2284 |
| 2285 @override |
| 2286 NumState add(InstanceState rightOperand) { |
| 2287 assertNumOrNull(rightOperand); |
| 2288 return _unknownNum(rightOperand); |
| 2289 } |
| 2290 |
| 2291 @override |
| 2292 IntState bitAnd(InstanceState rightOperand) { |
| 2293 assertIntOrNull(rightOperand); |
| 2294 return IntState.UNKNOWN_VALUE; |
| 2295 } |
| 2296 |
| 2297 @override |
| 2298 IntState bitNot() => IntState.UNKNOWN_VALUE; |
| 2299 |
| 2300 @override |
| 2301 IntState bitOr(InstanceState rightOperand) { |
| 2302 assertIntOrNull(rightOperand); |
| 2303 return IntState.UNKNOWN_VALUE; |
| 2304 } |
| 2305 |
| 2306 @override |
| 2307 IntState bitXor(InstanceState rightOperand) { |
| 2308 assertIntOrNull(rightOperand); |
| 2309 return IntState.UNKNOWN_VALUE; |
| 2310 } |
| 2311 |
| 2312 @override |
| 2313 StringState concatenate(InstanceState rightOperand) { |
| 2314 assertString(rightOperand); |
| 2315 return StringState.UNKNOWN_VALUE; |
| 2316 } |
| 2317 |
| 2318 @override |
| 2319 BoolState convertToBool() => BoolState.UNKNOWN_VALUE; |
| 2320 |
| 2321 @override |
| 2322 StringState convertToString() => StringState.UNKNOWN_VALUE; |
| 2323 |
| 2324 @override |
| 2325 NumState divide(InstanceState rightOperand) { |
| 2326 assertNumOrNull(rightOperand); |
| 2327 return _unknownNum(rightOperand); |
| 2328 } |
| 2329 |
| 2330 @override |
| 2331 BoolState equalEqual(InstanceState rightOperand) { |
| 2332 assertBoolNumStringOrNull(rightOperand); |
| 2333 return BoolState.UNKNOWN_VALUE; |
| 2334 } |
| 2335 |
| 2336 @override |
| 2337 String get typeName => "dynamic"; |
| 2338 |
| 2339 @override |
| 2340 BoolState greaterThan(InstanceState rightOperand) { |
| 2341 assertNumOrNull(rightOperand); |
| 2342 return BoolState.UNKNOWN_VALUE; |
| 2343 } |
| 2344 |
| 2345 @override |
| 2346 BoolState greaterThanOrEqual(InstanceState rightOperand) { |
| 2347 assertNumOrNull(rightOperand); |
| 2348 return BoolState.UNKNOWN_VALUE; |
| 2349 } |
| 2350 |
| 2351 @override |
| 2352 IntState integerDivide(InstanceState rightOperand) { |
| 2353 assertNumOrNull(rightOperand); |
| 2354 return IntState.UNKNOWN_VALUE; |
| 2355 } |
| 2356 |
| 2357 @override |
| 2358 bool get isBool => true; |
| 2359 |
| 2360 @override |
| 2361 bool get isBoolNumStringOrNull => true; |
| 2362 |
| 2363 @override |
| 2364 BoolState lessThan(InstanceState rightOperand) { |
| 2365 assertNumOrNull(rightOperand); |
| 2366 return BoolState.UNKNOWN_VALUE; |
| 2367 } |
| 2368 |
| 2369 @override |
| 2370 BoolState lessThanOrEqual(InstanceState rightOperand) { |
| 2371 assertNumOrNull(rightOperand); |
| 2372 return BoolState.UNKNOWN_VALUE; |
| 2373 } |
| 2374 |
| 2375 @override |
| 2376 BoolState logicalAnd(InstanceState rightOperand) { |
| 2377 assertBool(rightOperand); |
| 2378 return BoolState.UNKNOWN_VALUE; |
| 2379 } |
| 2380 |
| 2381 @override |
| 2382 BoolState logicalNot() => BoolState.UNKNOWN_VALUE; |
| 2383 |
| 2384 @override |
| 2385 BoolState logicalOr(InstanceState rightOperand) { |
| 2386 assertBool(rightOperand); |
| 2387 return rightOperand.convertToBool(); |
| 2388 } |
| 2389 |
| 2390 @override |
| 2391 NumState minus(InstanceState rightOperand) { |
| 2392 assertNumOrNull(rightOperand); |
| 2393 return _unknownNum(rightOperand); |
| 2394 } |
| 2395 |
| 2396 @override |
| 2397 NumState negated() => NumState.UNKNOWN_VALUE; |
| 2398 |
| 2399 @override |
| 2400 NumState remainder(InstanceState rightOperand) { |
| 2401 assertNumOrNull(rightOperand); |
| 2402 return _unknownNum(rightOperand); |
| 2403 } |
| 2404 |
| 2405 @override |
| 2406 IntState shiftLeft(InstanceState rightOperand) { |
| 2407 assertIntOrNull(rightOperand); |
| 2408 return IntState.UNKNOWN_VALUE; |
| 2409 } |
| 2410 |
| 2411 @override |
| 2412 IntState shiftRight(InstanceState rightOperand) { |
| 2413 assertIntOrNull(rightOperand); |
| 2414 return IntState.UNKNOWN_VALUE; |
| 2415 } |
| 2416 |
| 2417 @override |
| 2418 NumState times(InstanceState rightOperand) { |
| 2419 assertNumOrNull(rightOperand); |
| 2420 return _unknownNum(rightOperand); |
| 2421 } |
| 2422 |
| 2423 /** |
| 2424 * Return an object representing an unknown numeric value whose type is based
on the type of the |
| 2425 * right-hand operand. |
| 2426 * |
| 2427 * @param rightOperand the operand whose type will determine the type of the r
esult |
| 2428 * @return an object representing an unknown numeric value |
| 2429 */ |
| 2430 NumState _unknownNum(InstanceState rightOperand) { |
| 2431 if (rightOperand is IntState) { |
| 2432 return IntState.UNKNOWN_VALUE; |
| 2433 } else if (rightOperand is DoubleState) { |
| 2434 return DoubleState.UNKNOWN_VALUE; |
| 2435 } |
| 2436 return NumState.UNKNOWN_VALUE; |
| 2437 } |
| 2438 } |
| 2439 |
| 2440 /** |
| 2441 * Instances of the class `ErrorResult` represent the result of evaluating an ex
pression that |
| 2442 * is not a valid compile time constant. |
| 2443 */ |
| 2444 class ErrorResult extends EvaluationResultImpl { |
| 2445 /** |
| 2446 * The errors that prevent the expression from being a valid compile time cons
tant. |
| 2447 */ |
| 2448 List<ErrorResult_ErrorData> _errors = new List<ErrorResult_ErrorData>(); |
| 2449 |
| 2450 /** |
| 2451 * Initialize a newly created result representing the error with the given cod
e reported against |
| 2452 * the given node. |
| 2453 * |
| 2454 * @param node the node against which the error should be reported |
| 2455 * @param errorCode the error code for the error to be generated |
| 2456 */ |
| 2457 ErrorResult.con1(AstNode node, ErrorCode errorCode) { |
| 2458 _errors.add(new ErrorResult_ErrorData(node, errorCode)); |
| 2459 } |
| 2460 |
| 2461 /** |
| 2462 * Initialize a newly created result to represent the union of the errors in t
he given result |
| 2463 * objects. |
| 2464 * |
| 2465 * @param firstResult the first set of results being merged |
| 2466 * @param secondResult the second set of results being merged |
| 2467 */ |
| 2468 ErrorResult.con2(ErrorResult firstResult, ErrorResult secondResult) { |
| 2469 _errors.addAll(firstResult._errors); |
| 2470 _errors.addAll(secondResult._errors); |
| 2471 } |
| 2472 |
| 2473 @override |
| 2474 EvaluationResultImpl add(TypeProvider typeProvider, BinaryExpression node, Eva
luationResultImpl rightOperand) => rightOperand.addToError(node, this); |
| 2475 |
| 2476 @override |
| 2477 EvaluationResultImpl applyBooleanConversion(TypeProvider typeProvider, AstNode
node) => this; |
| 2478 |
| 2479 @override |
| 2480 EvaluationResultImpl bitAnd(TypeProvider typeProvider, BinaryExpression node,
EvaluationResultImpl rightOperand) => rightOperand.bitAndError(node, this); |
| 2481 |
| 2482 @override |
| 2483 EvaluationResultImpl bitNot(TypeProvider typeProvider, Expression node) => thi
s; |
| 2484 |
| 2485 @override |
| 2486 EvaluationResultImpl bitOr(TypeProvider typeProvider, BinaryExpression node, E
valuationResultImpl rightOperand) => rightOperand.bitOrError(node, this); |
| 2487 |
| 2488 @override |
| 2489 EvaluationResultImpl bitXor(TypeProvider typeProvider, BinaryExpression node,
EvaluationResultImpl rightOperand) => rightOperand.bitXorError(node, this); |
| 2490 |
| 2491 @override |
| 2492 EvaluationResultImpl concatenate(TypeProvider typeProvider, Expression node, E
valuationResultImpl rightOperand) => rightOperand.concatenateError(node, this); |
| 2493 |
| 2494 @override |
| 2495 EvaluationResultImpl divide(TypeProvider typeProvider, BinaryExpression node,
EvaluationResultImpl rightOperand) => rightOperand.divideError(node, this); |
| 2496 |
| 2497 @override |
| 2498 EvaluationResultImpl equalEqual(TypeProvider typeProvider, Expression node, Ev
aluationResultImpl rightOperand) => rightOperand.equalEqualError(node, this); |
| 2499 |
| 2500 @override |
| 2501 bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result) => fa
lse; |
| 2502 |
| 2503 List<ErrorResult_ErrorData> get errorData => _errors; |
| 2504 |
| 2505 @override |
| 2506 EvaluationResultImpl greaterThan(TypeProvider typeProvider, BinaryExpression n
ode, EvaluationResultImpl rightOperand) => rightOperand.greaterThanError(node, t
his); |
| 2507 |
| 2508 @override |
| 2509 EvaluationResultImpl greaterThanOrEqual(TypeProvider typeProvider, BinaryExpre
ssion node, EvaluationResultImpl rightOperand) => rightOperand.greaterThanOrEqua
lError(node, this); |
| 2510 |
| 2511 @override |
| 2512 EvaluationResultImpl integerDivide(TypeProvider typeProvider, BinaryExpression
node, EvaluationResultImpl rightOperand) => rightOperand.integerDivideError(nod
e, this); |
| 2513 |
| 2514 @override |
| 2515 EvaluationResultImpl integerDivideValid(TypeProvider typeProvider, BinaryExpre
ssion node, ValidResult leftOperand) => this; |
| 2516 |
| 2517 @override |
| 2518 EvaluationResultImpl lessThan(TypeProvider typeProvider, BinaryExpression node
, EvaluationResultImpl rightOperand) => rightOperand.lessThanError(node, this); |
| 2519 |
| 2520 @override |
| 2521 EvaluationResultImpl lessThanOrEqual(TypeProvider typeProvider, BinaryExpressi
on node, EvaluationResultImpl rightOperand) => rightOperand.lessThanOrEqualError
(node, this); |
| 2522 |
| 2523 @override |
| 2524 EvaluationResultImpl logicalAnd(TypeProvider typeProvider, BinaryExpression no
de, EvaluationResultImpl rightOperand) => rightOperand.logicalAndError(node, thi
s); |
| 2525 |
| 2526 @override |
| 2527 EvaluationResultImpl logicalNot(TypeProvider typeProvider, Expression node) =>
this; |
| 2528 |
| 2529 @override |
| 2530 EvaluationResultImpl logicalOr(TypeProvider typeProvider, BinaryExpression nod
e, EvaluationResultImpl rightOperand) => rightOperand.logicalOrError(node, this)
; |
| 2531 |
| 2532 @override |
| 2533 EvaluationResultImpl minus(TypeProvider typeProvider, BinaryExpression node, E
valuationResultImpl rightOperand) => rightOperand.minusError(node, this); |
| 2534 |
| 2535 @override |
| 2536 EvaluationResultImpl negated(TypeProvider typeProvider, Expression node) => th
is; |
| 2537 |
| 2538 @override |
| 2539 EvaluationResultImpl notEqual(TypeProvider typeProvider, BinaryExpression node
, EvaluationResultImpl rightOperand) => rightOperand.notEqualError(node, this); |
| 2540 |
| 2541 @override |
| 2542 EvaluationResultImpl performToString(TypeProvider typeProvider, AstNode node)
=> this; |
| 2543 |
| 2544 @override |
| 2545 EvaluationResultImpl remainder(TypeProvider typeProvider, BinaryExpression nod
e, EvaluationResultImpl rightOperand) => rightOperand.remainderError(node, this)
; |
| 2546 |
| 2547 @override |
| 2548 EvaluationResultImpl shiftLeft(TypeProvider typeProvider, BinaryExpression nod
e, EvaluationResultImpl rightOperand) => rightOperand.shiftLeftError(node, this)
; |
| 2549 |
| 2550 @override |
| 2551 EvaluationResultImpl shiftRight(TypeProvider typeProvider, BinaryExpression no
de, EvaluationResultImpl rightOperand) => rightOperand.shiftRightError(node, thi
s); |
| 2552 |
| 2553 @override |
| 2554 EvaluationResultImpl times(TypeProvider typeProvider, BinaryExpression node, E
valuationResultImpl rightOperand) => rightOperand.timesError(node, this); |
| 2555 |
| 2556 @override |
| 2557 EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand
) => new ErrorResult.con2(this, leftOperand); |
| 2558 |
| 2559 @override |
| 2560 EvaluationResultImpl addToValid(TypeProvider typeProvider, BinaryExpression no
de, ValidResult leftOperand) => this; |
| 2561 |
| 2562 @override |
| 2563 EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperan
d) => new ErrorResult.con2(this, leftOperand); |
| 2564 |
| 2565 @override |
| 2566 EvaluationResultImpl bitAndValid(TypeProvider typeProvider, BinaryExpression n
ode, ValidResult leftOperand) => this; |
| 2567 |
| 2568 @override |
| 2569 EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand
) => new ErrorResult.con2(this, leftOperand); |
| 2570 |
| 2571 @override |
| 2572 EvaluationResultImpl bitOrValid(TypeProvider typeProvider, BinaryExpression no
de, ValidResult leftOperand) => this; |
| 2573 |
| 2574 @override |
| 2575 EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperan
d) => new ErrorResult.con2(this, leftOperand); |
| 2576 |
| 2577 @override |
| 2578 EvaluationResultImpl bitXorValid(TypeProvider typeProvider, BinaryExpression n
ode, ValidResult leftOperand) => this; |
| 2579 |
| 2580 @override |
| 2581 EvaluationResultImpl concatenateError(Expression node, ErrorResult leftOperand
) => new ErrorResult.con2(this, leftOperand); |
| 2582 |
| 2583 @override |
| 2584 EvaluationResultImpl concatenateValid(TypeProvider typeProvider, Expression no
de, ValidResult leftOperand) => this; |
| 2585 |
| 2586 @override |
| 2587 EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperan
d) => new ErrorResult.con2(this, leftOperand); |
| 2588 |
| 2589 @override |
| 2590 EvaluationResultImpl divideValid(TypeProvider typeProvider, BinaryExpression n
ode, ValidResult leftOperand) => this; |
| 2591 |
| 2592 @override |
| 2593 EvaluationResultImpl equalEqualError(Expression node, ErrorResult leftOperand)
=> new ErrorResult.con2(this, leftOperand); |
| 2594 |
| 2595 @override |
| 2596 EvaluationResultImpl equalEqualValid(TypeProvider typeProvider, Expression nod
e, ValidResult leftOperand) => this; |
| 2597 |
| 2598 @override |
| 2599 EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftO
perand) => new ErrorResult.con2(this, leftOperand); |
| 2600 |
| 2601 @override |
| 2602 EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResul
t leftOperand) => new ErrorResult.con2(this, leftOperand); |
| 2603 |
| 2604 @override |
| 2605 EvaluationResultImpl greaterThanOrEqualValid(TypeProvider typeProvider, Binary
Expression node, ValidResult leftOperand) => this; |
| 2606 |
| 2607 @override |
| 2608 EvaluationResultImpl greaterThanValid(TypeProvider typeProvider, BinaryExpress
ion node, ValidResult leftOperand) => this; |
| 2609 |
| 2610 @override |
| 2611 EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult lef
tOperand) => new ErrorResult.con2(this, leftOperand); |
| 2612 |
| 2613 @override |
| 2614 EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOper
and) => new ErrorResult.con2(this, leftOperand); |
| 2615 |
| 2616 @override |
| 2617 EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult l
eftOperand) => new ErrorResult.con2(this, leftOperand); |
| 2618 |
| 2619 @override |
| 2620 EvaluationResultImpl lessThanOrEqualValid(TypeProvider typeProvider, BinaryExp
ression node, ValidResult leftOperand) => this; |
| 2621 |
| 2622 @override |
| 2623 EvaluationResultImpl lessThanValid(TypeProvider typeProvider, BinaryExpression
node, ValidResult leftOperand) => this; |
| 2624 |
| 2625 @override |
| 2626 EvaluationResultImpl logicalAndError(BinaryExpression node, ErrorResult leftOp
erand) => new ErrorResult.con2(this, leftOperand); |
| 2627 |
| 2628 @override |
| 2629 EvaluationResultImpl logicalAndValid(TypeProvider typeProvider, BinaryExpressi
on node, ValidResult leftOperand) => this; |
| 2630 |
| 2631 @override |
| 2632 EvaluationResultImpl logicalOrError(BinaryExpression node, ErrorResult leftOpe
rand) => new ErrorResult.con2(this, leftOperand); |
| 2633 |
| 2634 @override |
| 2635 EvaluationResultImpl logicalOrValid(TypeProvider typeProvider, BinaryExpressio
n node, ValidResult leftOperand) => this; |
| 2636 |
| 2637 @override |
| 2638 EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand
) => new ErrorResult.con2(this, leftOperand); |
| 2639 |
| 2640 @override |
| 2641 EvaluationResultImpl minusValid(TypeProvider typeProvider, BinaryExpression no
de, ValidResult leftOperand) => this; |
| 2642 |
| 2643 @override |
| 2644 EvaluationResultImpl notEqualError(BinaryExpression node, ErrorResult leftOper
and) => new ErrorResult.con2(this, leftOperand); |
| 2645 |
| 2646 @override |
| 2647 EvaluationResultImpl notEqualValid(TypeProvider typeProvider, BinaryExpression
node, ValidResult leftOperand) => this; |
| 2648 |
| 2649 @override |
| 2650 EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOpe
rand) => new ErrorResult.con2(this, leftOperand); |
| 2651 |
| 2652 @override |
| 2653 EvaluationResultImpl remainderValid(TypeProvider typeProvider, BinaryExpressio
n node, ValidResult leftOperand) => this; |
| 2654 |
| 2655 @override |
| 2656 EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOpe
rand) => new ErrorResult.con2(this, leftOperand); |
| 2657 |
| 2658 @override |
| 2659 EvaluationResultImpl shiftLeftValid(TypeProvider typeProvider, BinaryExpressio
n node, ValidResult leftOperand) => this; |
| 2660 |
| 2661 @override |
| 2662 EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOp
erand) => new ErrorResult.con2(this, leftOperand); |
| 2663 |
| 2664 @override |
| 2665 EvaluationResultImpl shiftRightValid(TypeProvider typeProvider, BinaryExpressi
on node, ValidResult leftOperand) => this; |
| 2666 |
| 2667 @override |
| 2668 EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand
) => new ErrorResult.con2(this, leftOperand); |
| 2669 |
| 2670 @override |
| 2671 EvaluationResultImpl timesValid(TypeProvider typeProvider, BinaryExpression no
de, ValidResult leftOperand) => this; |
| 2672 } |
| 2673 |
| 2674 class ErrorResult_ErrorData { |
| 2675 /** |
| 2676 * The node against which the error should be reported. |
| 2677 */ |
| 2678 final AstNode node; |
| 2679 |
| 2680 /** |
| 2681 * The error code for the error to be generated. |
| 2682 */ |
| 2683 final ErrorCode errorCode; |
| 2684 |
| 2685 /** |
| 2686 * Initialize a newly created data holder to represent the error with the give
n code reported |
| 2687 * against the given node. |
| 2688 * |
| 2689 * @param node the node against which the error should be reported |
| 2690 * @param errorCode the error code for the error to be generated |
| 2691 */ |
| 2692 ErrorResult_ErrorData(this.node, this.errorCode); |
| 2693 } |
| 2694 |
| 2695 /** |
| 2696 * Instances of the class `EvaluationException` represent a run-time exception t
hat would be |
| 2697 * thrown during the evaluation of Dart code. |
| 2698 */ |
| 2699 class EvaluationException extends JavaException { |
| 2700 /** |
| 2701 * The error code associated with the exception. |
| 2702 */ |
| 2703 final ErrorCode errorCode; |
| 2704 |
| 2705 /** |
| 2706 * Initialize a newly created exception to have the given error code. |
| 2707 * |
| 2708 * @param errorCode the error code associated with the exception |
| 2709 */ |
| 2710 EvaluationException(this.errorCode); |
| 2711 } |
| 2712 |
| 2713 /** |
| 2714 * Instances of the class `EvaluationResult` represent the result of attempting
to evaluate an |
| 2715 * expression. |
| 2716 */ |
| 2717 class EvaluationResult { |
| 2718 /** |
| 2719 * Return an evaluation result representing the result of evaluating an expres
sion that is not a |
| 2720 * compile-time constant because of the given errors. |
| 2721 * |
| 2722 * @param errors the errors that should be reported for the expression(s) that
were evaluated |
| 2723 * @return the result of evaluating an expression that is not a compile-time c
onstant |
| 2724 */ |
| 2725 static EvaluationResult forErrors(List<AnalysisError> errors) => new Evaluatio
nResult(null, errors); |
| 2726 |
| 2727 /** |
| 2728 * Return an evaluation result representing the result of evaluating an expres
sion that is a |
| 2729 * compile-time constant that evaluates to the given value. |
| 2730 * |
| 2731 * @param value the value of the expression |
| 2732 * @return the result of evaluating an expression that is a compile-time const
ant |
| 2733 */ |
| 2734 static EvaluationResult forValue(DartObject value) => new EvaluationResult(val
ue, null); |
| 2735 |
| 2736 /** |
| 2737 * The value of the expression. |
| 2738 */ |
| 2739 final DartObject value; |
| 2740 |
| 2741 /** |
| 2742 * The errors that should be reported for the expression(s) that were evaluate
d. |
| 2743 */ |
| 2744 final List<AnalysisError> _errors; |
| 2745 |
| 2746 /** |
| 2747 * Initialize a newly created result object with the given state. Clients shou
ld use one of the |
| 2748 * factory methods: [forErrors] and [forValue]. |
| 2749 * |
| 2750 * @param value the value of the expression |
| 2751 * @param errors the errors that should be reported for the expression(s) that
were evaluated |
| 2752 */ |
| 2753 EvaluationResult(this.value, this._errors); |
| 2754 |
| 2755 /** |
| 2756 * Return an array containing the errors that should be reported for the expre
ssion(s) that were |
| 2757 * evaluated. If there are no such errors, the array will be empty. The array
can be empty even if |
| 2758 * the expression is not a valid compile time constant if the errors would hav
e been reported by |
| 2759 * other parts of the analysis engine. |
| 2760 */ |
| 2761 List<AnalysisError> get errors => _errors == null ? AnalysisError.NO_ERRORS :
_errors; |
| 2762 |
| 2763 /** |
| 2764 * Return `true` if the expression is a compile-time constant expression that
would not |
| 2765 * throw an exception when evaluated. |
| 2766 * |
| 2767 * @return `true` if the expression is a valid compile-time constant expressio
n |
| 2768 */ |
| 2769 bool get isValid => _errors == null; |
| 2770 } |
| 2771 |
| 2772 /** |
| 2773 * Instances of the class `InternalResult` represent the result of attempting to
evaluate a |
| 2774 * expression. |
| 2775 */ |
| 2776 abstract class EvaluationResultImpl { |
| 2777 EvaluationResultImpl add(TypeProvider typeProvider, BinaryExpression node, Eva
luationResultImpl rightOperand); |
| 2778 |
| 2779 /** |
| 2780 * Return the result of applying boolean conversion to this result. |
| 2781 * |
| 2782 * @param typeProvider the type provider used to access known types |
| 2783 * @param node the node against which errors should be reported |
| 2784 * @return the result of applying boolean conversion to the given value |
| 2785 */ |
| 2786 EvaluationResultImpl applyBooleanConversion(TypeProvider typeProvider, AstNode
node); |
| 2787 |
| 2788 EvaluationResultImpl bitAnd(TypeProvider typeProvider, BinaryExpression node,
EvaluationResultImpl rightOperand); |
| 2789 |
| 2790 EvaluationResultImpl bitNot(TypeProvider typeProvider, Expression node); |
| 2791 |
| 2792 EvaluationResultImpl bitOr(TypeProvider typeProvider, BinaryExpression node, E
valuationResultImpl rightOperand); |
| 2793 |
| 2794 EvaluationResultImpl bitXor(TypeProvider typeProvider, BinaryExpression node,
EvaluationResultImpl rightOperand); |
| 2795 |
| 2796 EvaluationResultImpl concatenate(TypeProvider typeProvider, Expression node, E
valuationResultImpl rightOperand); |
| 2797 |
| 2798 EvaluationResultImpl divide(TypeProvider typeProvider, BinaryExpression node,
EvaluationResultImpl rightOperand); |
| 2799 |
| 2800 EvaluationResultImpl equalEqual(TypeProvider typeProvider, Expression node, Ev
aluationResultImpl rightOperand); |
| 2801 |
| 2802 bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result); |
| 2803 |
| 2804 EvaluationResultImpl greaterThan(TypeProvider typeProvider, BinaryExpression n
ode, EvaluationResultImpl rightOperand); |
| 2805 |
| 2806 EvaluationResultImpl greaterThanOrEqual(TypeProvider typeProvider, BinaryExpre
ssion node, EvaluationResultImpl rightOperand); |
| 2807 |
| 2808 EvaluationResultImpl integerDivide(TypeProvider typeProvider, BinaryExpression
node, EvaluationResultImpl rightOperand); |
| 2809 |
| 2810 EvaluationResultImpl lessThan(TypeProvider typeProvider, BinaryExpression node
, EvaluationResultImpl rightOperand); |
| 2811 |
| 2812 EvaluationResultImpl lessThanOrEqual(TypeProvider typeProvider, BinaryExpressi
on node, EvaluationResultImpl rightOperand); |
| 2813 |
| 2814 EvaluationResultImpl logicalAnd(TypeProvider typeProvider, BinaryExpression no
de, EvaluationResultImpl rightOperand); |
| 2815 |
| 2816 EvaluationResultImpl logicalNot(TypeProvider typeProvider, Expression node); |
| 2817 |
| 2818 EvaluationResultImpl logicalOr(TypeProvider typeProvider, BinaryExpression nod
e, EvaluationResultImpl rightOperand); |
| 2819 |
| 2820 EvaluationResultImpl minus(TypeProvider typeProvider, BinaryExpression node, E
valuationResultImpl rightOperand); |
| 2821 |
| 2822 EvaluationResultImpl negated(TypeProvider typeProvider, Expression node); |
| 2823 |
| 2824 EvaluationResultImpl notEqual(TypeProvider typeProvider, BinaryExpression node
, EvaluationResultImpl rightOperand); |
| 2825 |
| 2826 EvaluationResultImpl performToString(TypeProvider typeProvider, AstNode node); |
| 2827 |
| 2828 EvaluationResultImpl remainder(TypeProvider typeProvider, BinaryExpression nod
e, EvaluationResultImpl rightOperand); |
| 2829 |
| 2830 EvaluationResultImpl shiftLeft(TypeProvider typeProvider, BinaryExpression nod
e, EvaluationResultImpl rightOperand); |
| 2831 |
| 2832 EvaluationResultImpl shiftRight(TypeProvider typeProvider, BinaryExpression no
de, EvaluationResultImpl rightOperand); |
| 2833 |
| 2834 EvaluationResultImpl times(TypeProvider typeProvider, BinaryExpression node, E
valuationResultImpl rightOperand); |
| 2835 |
| 2836 EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand
); |
| 2837 |
| 2838 EvaluationResultImpl addToValid(TypeProvider typeProvider, BinaryExpression no
de, ValidResult leftOperand); |
| 2839 |
| 2840 EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperan
d); |
| 2841 |
| 2842 EvaluationResultImpl bitAndValid(TypeProvider typeProvider, BinaryExpression n
ode, ValidResult leftOperand); |
| 2843 |
| 2844 EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand
); |
| 2845 |
| 2846 EvaluationResultImpl bitOrValid(TypeProvider typeProvider, BinaryExpression no
de, ValidResult leftOperand); |
| 2847 |
| 2848 EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperan
d); |
| 2849 |
| 2850 EvaluationResultImpl bitXorValid(TypeProvider typeProvider, BinaryExpression n
ode, ValidResult leftOperand); |
| 2851 |
| 2852 EvaluationResultImpl concatenateError(Expression node, ErrorResult leftOperand
); |
| 2853 |
| 2854 EvaluationResultImpl concatenateValid(TypeProvider typeProvider, Expression no
de, ValidResult leftOperand); |
| 2855 |
| 2856 EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperan
d); |
| 2857 |
| 2858 EvaluationResultImpl divideValid(TypeProvider typeProvider, BinaryExpression n
ode, ValidResult leftOperand); |
| 2859 |
| 2860 EvaluationResultImpl equalEqualError(Expression node, ErrorResult leftOperand)
; |
| 2861 |
| 2862 EvaluationResultImpl equalEqualValid(TypeProvider typeProvider, Expression nod
e, ValidResult leftOperand); |
| 2863 |
| 2864 EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftO
perand); |
| 2865 |
| 2866 EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResul
t leftOperand); |
| 2867 |
| 2868 EvaluationResultImpl greaterThanOrEqualValid(TypeProvider typeProvider, Binary
Expression node, ValidResult leftOperand); |
| 2869 |
| 2870 EvaluationResultImpl greaterThanValid(TypeProvider typeProvider, BinaryExpress
ion node, ValidResult leftOperand); |
| 2871 |
| 2872 EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult lef
tOperand); |
| 2873 |
| 2874 EvaluationResultImpl integerDivideValid(TypeProvider typeProvider, BinaryExpre
ssion node, ValidResult leftOperand); |
| 2875 |
| 2876 EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOper
and); |
| 2877 |
| 2878 EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult l
eftOperand); |
| 2879 |
| 2880 EvaluationResultImpl lessThanOrEqualValid(TypeProvider typeProvider, BinaryExp
ression node, ValidResult leftOperand); |
| 2881 |
| 2882 EvaluationResultImpl lessThanValid(TypeProvider typeProvider, BinaryExpression
node, ValidResult leftOperand); |
| 2883 |
| 2884 EvaluationResultImpl logicalAndError(BinaryExpression node, ErrorResult leftOp
erand); |
| 2885 |
| 2886 EvaluationResultImpl logicalAndValid(TypeProvider typeProvider, BinaryExpressi
on node, ValidResult leftOperand); |
| 2887 |
| 2888 EvaluationResultImpl logicalOrError(BinaryExpression node, ErrorResult leftOpe
rand); |
| 2889 |
| 2890 EvaluationResultImpl logicalOrValid(TypeProvider typeProvider, BinaryExpressio
n node, ValidResult leftOperand); |
| 2891 |
| 2892 EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand
); |
| 2893 |
| 2894 EvaluationResultImpl minusValid(TypeProvider typeProvider, BinaryExpression no
de, ValidResult leftOperand); |
| 2895 |
| 2896 EvaluationResultImpl notEqualError(BinaryExpression node, ErrorResult leftOper
and); |
| 2897 |
| 2898 EvaluationResultImpl notEqualValid(TypeProvider typeProvider, BinaryExpression
node, ValidResult leftOperand); |
| 2899 |
| 2900 EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOpe
rand); |
| 2901 |
| 2902 EvaluationResultImpl remainderValid(TypeProvider typeProvider, BinaryExpressio
n node, ValidResult leftOperand); |
| 2903 |
| 2904 EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOpe
rand); |
| 2905 |
| 2906 EvaluationResultImpl shiftLeftValid(TypeProvider typeProvider, BinaryExpressio
n node, ValidResult leftOperand); |
| 2907 |
| 2908 EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOp
erand); |
| 2909 |
| 2910 EvaluationResultImpl shiftRightValid(TypeProvider typeProvider, BinaryExpressi
on node, ValidResult leftOperand); |
| 2911 |
| 2912 EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand
); |
| 2913 |
| 2914 EvaluationResultImpl timesValid(TypeProvider typeProvider, BinaryExpression no
de, ValidResult leftOperand); |
| 2915 } |
| 2916 |
| 2917 /** |
| 2918 * Instances of the class `FunctionState` represent the state of an object repre
senting a |
| 2919 * function. |
| 2920 */ |
| 2921 class FunctionState extends InstanceState { |
| 2922 /** |
| 2923 * The element representing the function being modeled. |
| 2924 */ |
| 2925 final ExecutableElement _element; |
| 2926 |
| 2927 /** |
| 2928 * Initialize a newly created state to represent the given function. |
| 2929 * |
| 2930 * @param element the element representing the function being modeled |
| 2931 */ |
| 2932 FunctionState(this._element); |
| 2933 |
| 2934 @override |
| 2935 StringState convertToString() { |
| 2936 if (_element == null) { |
| 2937 return StringState.UNKNOWN_VALUE; |
| 2938 } |
| 2939 return new StringState(_element.name); |
| 2940 } |
| 2941 |
| 2942 @override |
| 2943 bool operator ==(Object object) => object is FunctionState && (_element == obj
ect._element); |
| 2944 |
| 2945 @override |
| 2946 BoolState equalEqual(InstanceState rightOperand) { |
| 2947 if (_element == null) { |
| 2948 return BoolState.UNKNOWN_VALUE; |
| 2949 } |
| 2950 if (rightOperand is FunctionState) { |
| 2951 ExecutableElement rightElement = rightOperand._element; |
| 2952 if (rightElement == null) { |
| 2953 return BoolState.UNKNOWN_VALUE; |
| 2954 } |
| 2955 return BoolState.from(_element == rightElement); |
| 2956 } else if (rightOperand is DynamicState) { |
| 2957 return BoolState.UNKNOWN_VALUE; |
| 2958 } |
| 2959 return BoolState.FALSE_STATE; |
| 2960 } |
| 2961 |
| 2962 @override |
| 2963 String get typeName => "Function"; |
| 2964 |
| 2965 @override |
| 2966 int get hashCode => _element == null ? 0 : _element.hashCode; |
| 2967 |
| 2968 @override |
| 2969 String toString() => _element == null ? "-unknown-" : _element.name; |
| 2970 } |
| 2971 |
| 2972 /** |
| 2973 * Instances of the class `GenericState` represent the state of an object repres
enting a Dart |
| 2974 * object for which there is no more specific state. |
| 2975 */ |
| 2976 class GenericState extends InstanceState { |
| 2977 /** |
| 2978 * The values of the fields of this instance. |
| 2979 */ |
| 2980 final HashMap<String, DartObjectImpl> _fieldMap; |
| 2981 |
| 2982 /** |
| 2983 * Pseudo-field that we use to represent fields in the superclass. |
| 2984 */ |
| 2985 static String SUPERCLASS_FIELD = "(super)"; |
| 2986 |
| 2987 /** |
| 2988 * A state that can be used to represent an object whose state is not known. |
| 2989 */ |
| 2990 static GenericState UNKNOWN_VALUE = new GenericState(new HashMap<String, DartO
bjectImpl>()); |
| 2991 |
| 2992 /** |
| 2993 * Initialize a newly created state to represent a newly created object. |
| 2994 * |
| 2995 * @param fieldMap the values of the fields of this instance |
| 2996 */ |
| 2997 GenericState(this._fieldMap); |
| 2998 |
| 2999 @override |
| 3000 StringState convertToString() => StringState.UNKNOWN_VALUE; |
| 3001 |
| 3002 @override |
| 3003 BoolState equalEqual(InstanceState rightOperand) { |
| 3004 assertBoolNumStringOrNull(rightOperand); |
| 3005 if (rightOperand is DynamicState) { |
| 3006 return BoolState.UNKNOWN_VALUE; |
| 3007 } |
| 3008 return BoolState.from(this == rightOperand); |
| 3009 } |
| 3010 |
| 3011 @override |
| 3012 bool operator ==(Object object) { |
| 3013 if (object is! GenericState) { |
| 3014 return false; |
| 3015 } |
| 3016 GenericState state = object as GenericState; |
| 3017 HashSet<String> otherFields = new HashSet<String>.from(state._fieldMap.keys.
toSet()); |
| 3018 for (String fieldName in _fieldMap.keys.toSet()) { |
| 3019 if (_fieldMap[fieldName] != state._fieldMap[fieldName]) { |
| 3020 return false; |
| 3021 } |
| 3022 otherFields.remove(fieldName); |
| 3023 } |
| 3024 for (String fieldName in otherFields) { |
| 3025 if (state._fieldMap[fieldName] != _fieldMap[fieldName]) { |
| 3026 return false; |
| 3027 } |
| 3028 } |
| 3029 return true; |
| 3030 } |
| 3031 |
| 3032 @override |
| 3033 HashMap<String, DartObjectImpl> get fields => _fieldMap; |
| 3034 |
| 3035 @override |
| 3036 String get typeName => "user defined type"; |
| 3037 |
| 3038 @override |
| 3039 int get hashCode { |
| 3040 int hashCode = 0; |
| 3041 for (DartObjectImpl value in _fieldMap.values) { |
| 3042 hashCode += value.hashCode; |
| 3043 } |
| 3044 return hashCode; |
| 3045 } |
| 3046 |
| 3047 @override |
| 3048 bool get isUnknown => identical(this, UNKNOWN_VALUE); |
| 3049 } |
| 3050 |
| 3051 /** |
| 3052 * The class `InstanceState` defines the behavior of objects representing the st
ate of a Dart |
| 3053 * object. |
| 3054 */ |
| 3055 abstract class InstanceState { |
| 3056 /** |
| 3057 * Return the result of invoking the '+' operator on this object with the give
n argument. |
| 3058 * |
| 3059 * @param rightOperand the right-hand operand of the operation |
| 3060 * @return the result of invoking the '+' operator on this object with the giv
en argument |
| 3061 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3062 */ |
| 3063 NumState add(InstanceState rightOperand) { |
| 3064 assertNumOrNull(this); |
| 3065 assertNumOrNull(rightOperand); |
| 3066 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3067 } |
| 3068 |
| 3069 /** |
| 3070 * Return the result of invoking the '&' operator on this object with the give
n argument. |
| 3071 * |
| 3072 * @param rightOperand the right-hand operand of the operation |
| 3073 * @return the result of invoking the '&' operator on this object with the giv
en argument |
| 3074 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3075 */ |
| 3076 IntState bitAnd(InstanceState rightOperand) { |
| 3077 assertIntOrNull(this); |
| 3078 assertIntOrNull(rightOperand); |
| 3079 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3080 } |
| 3081 |
| 3082 /** |
| 3083 * Return the result of invoking the '~' operator on this object. |
| 3084 * |
| 3085 * @return the result of invoking the '~' operator on this object |
| 3086 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3087 */ |
| 3088 IntState bitNot() { |
| 3089 assertIntOrNull(this); |
| 3090 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3091 } |
| 3092 |
| 3093 /** |
| 3094 * Return the result of invoking the '|' operator on this object with the give
n argument. |
| 3095 * |
| 3096 * @param rightOperand the right-hand operand of the operation |
| 3097 * @return the result of invoking the '|' operator on this object with the giv
en argument |
| 3098 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3099 */ |
| 3100 IntState bitOr(InstanceState rightOperand) { |
| 3101 assertIntOrNull(this); |
| 3102 assertIntOrNull(rightOperand); |
| 3103 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3104 } |
| 3105 |
| 3106 /** |
| 3107 * Return the result of invoking the '^' operator on this object with the give
n argument. |
| 3108 * |
| 3109 * @param rightOperand the right-hand operand of the operation |
| 3110 * @return the result of invoking the '^' operator on this object with the giv
en argument |
| 3111 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3112 */ |
| 3113 IntState bitXor(InstanceState rightOperand) { |
| 3114 assertIntOrNull(this); |
| 3115 assertIntOrNull(rightOperand); |
| 3116 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3117 } |
| 3118 |
| 3119 /** |
| 3120 * Return the result of invoking the ' ' operator on this object with the give
n argument. |
| 3121 * |
| 3122 * @param rightOperand the right-hand operand of the operation |
| 3123 * @return the result of invoking the ' ' operator on this object with the giv
en argument |
| 3124 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3125 */ |
| 3126 StringState concatenate(InstanceState rightOperand) { |
| 3127 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3128 } |
| 3129 |
| 3130 /** |
| 3131 * Return the result of applying boolean conversion to this object. |
| 3132 * |
| 3133 * @param typeProvider the type provider used to find known types |
| 3134 * @return the result of applying boolean conversion to this object |
| 3135 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3136 */ |
| 3137 BoolState convertToBool() => BoolState.FALSE_STATE; |
| 3138 |
| 3139 /** |
| 3140 * Return the result of converting this object to a String. |
| 3141 * |
| 3142 * @return the result of converting this object to a String |
| 3143 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3144 */ |
| 3145 StringState convertToString(); |
| 3146 |
| 3147 /** |
| 3148 * Return the result of invoking the '/' operator on this object with the give
n argument. |
| 3149 * |
| 3150 * @param rightOperand the right-hand operand of the operation |
| 3151 * @return the result of invoking the '/' operator on this object with the giv
en argument |
| 3152 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3153 */ |
| 3154 NumState divide(InstanceState rightOperand) { |
| 3155 assertNumOrNull(this); |
| 3156 assertNumOrNull(rightOperand); |
| 3157 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3158 } |
| 3159 |
| 3160 /** |
| 3161 * Return the result of invoking the '==' operator on this object with the giv
en argument. |
| 3162 * |
| 3163 * @param rightOperand the right-hand operand of the operation |
| 3164 * @return the result of invoking the '==' operator on this object with the gi
ven argument |
| 3165 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3166 */ |
| 3167 BoolState equalEqual(InstanceState rightOperand); |
| 3168 |
| 3169 /** |
| 3170 * If this represents a generic dart object, return a map from its fieldnames
to their values. |
| 3171 * Otherwise return null. |
| 3172 */ |
| 3173 HashMap<String, DartObjectImpl> get fields => null; |
| 3174 |
| 3175 /** |
| 3176 * Return the name of the type of this value. |
| 3177 * |
| 3178 * @return the name of the type of this value |
| 3179 */ |
| 3180 String get typeName; |
| 3181 |
| 3182 /** |
| 3183 * Return this object's value if it can be represented exactly, or `null` if e
ither the |
| 3184 * value cannot be represented exactly or if the value is `null`. Clients shou
ld use |
| 3185 * [hasExactValue] to distinguish between these two cases. |
| 3186 * |
| 3187 * @return this object's value |
| 3188 */ |
| 3189 Object get value => null; |
| 3190 |
| 3191 /** |
| 3192 * Return the result of invoking the '>' operator on this object with the g
iven argument. |
| 3193 * |
| 3194 * @param rightOperand the right-hand operand of the operation |
| 3195 * @return the result of invoking the '>' operator on this object with the
given argument |
| 3196 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3197 */ |
| 3198 BoolState greaterThan(InstanceState rightOperand) { |
| 3199 assertNumOrNull(this); |
| 3200 assertNumOrNull(rightOperand); |
| 3201 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3202 } |
| 3203 |
| 3204 /** |
| 3205 * Return the result of invoking the '>=' operator on this object with the
given argument. |
| 3206 * |
| 3207 * @param rightOperand the right-hand operand of the operation |
| 3208 * @return the result of invoking the '>=' operator on this object with the
given argument |
| 3209 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3210 */ |
| 3211 BoolState greaterThanOrEqual(InstanceState rightOperand) { |
| 3212 assertNumOrNull(this); |
| 3213 assertNumOrNull(rightOperand); |
| 3214 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3215 } |
| 3216 |
| 3217 /** |
| 3218 * Return `true` if this object's value can be represented exactly. |
| 3219 * |
| 3220 * @return `true` if this object's value can be represented exactly |
| 3221 */ |
| 3222 bool get hasExactValue => false; |
| 3223 |
| 3224 /** |
| 3225 * Return the result of invoking the '~/' operator on this object with the giv
en argument. |
| 3226 * |
| 3227 * @param rightOperand the right-hand operand of the operation |
| 3228 * @return the result of invoking the '~/' operator on this object with the gi
ven argument |
| 3229 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3230 */ |
| 3231 IntState integerDivide(InstanceState rightOperand) { |
| 3232 assertNumOrNull(this); |
| 3233 assertNumOrNull(rightOperand); |
| 3234 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3235 } |
| 3236 |
| 3237 /** |
| 3238 * Return `true` if this object represents an object whose type is 'bool'. |
| 3239 * |
| 3240 * @return `true` if this object represents a boolean value |
| 3241 */ |
| 3242 bool get isBool => false; |
| 3243 |
| 3244 /** |
| 3245 * Return `true` if this object represents an object whose type is either 'boo
l', 'num', |
| 3246 * 'String', or 'Null'. |
| 3247 * |
| 3248 * @return `true` if this object represents either a boolean, numeric, string
or null value |
| 3249 */ |
| 3250 bool get isBoolNumStringOrNull => false; |
| 3251 |
| 3252 /** |
| 3253 * Return true if this object represents an unknown value. |
| 3254 */ |
| 3255 bool get isUnknown => false; |
| 3256 |
| 3257 /** |
| 3258 * Return the result of invoking the '<' operator on this object with the g
iven argument. |
| 3259 * |
| 3260 * @param rightOperand the right-hand operand of the operation |
| 3261 * @return the result of invoking the '<' operator on this object with the
given argument |
| 3262 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3263 */ |
| 3264 BoolState lessThan(InstanceState rightOperand) { |
| 3265 assertNumOrNull(this); |
| 3266 assertNumOrNull(rightOperand); |
| 3267 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3268 } |
| 3269 |
| 3270 /** |
| 3271 * Return the result of invoking the '<=' operator on this object with the
given argument. |
| 3272 * |
| 3273 * @param rightOperand the right-hand operand of the operation |
| 3274 * @return the result of invoking the '<=' operator on this object with the
given argument |
| 3275 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3276 */ |
| 3277 BoolState lessThanOrEqual(InstanceState rightOperand) { |
| 3278 assertNumOrNull(this); |
| 3279 assertNumOrNull(rightOperand); |
| 3280 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3281 } |
| 3282 |
| 3283 /** |
| 3284 * Return the result of invoking the '&&' operator on this object with the giv
en argument. |
| 3285 * |
| 3286 * @param rightOperand the right-hand operand of the operation |
| 3287 * @return the result of invoking the '&&' operator on this object with the gi
ven argument |
| 3288 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3289 */ |
| 3290 BoolState logicalAnd(InstanceState rightOperand) { |
| 3291 assertBool(this); |
| 3292 assertBool(rightOperand); |
| 3293 return BoolState.FALSE_STATE; |
| 3294 } |
| 3295 |
| 3296 /** |
| 3297 * Return the result of invoking the '!' operator on this object. |
| 3298 * |
| 3299 * @return the result of invoking the '!' operator on this object |
| 3300 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3301 */ |
| 3302 BoolState logicalNot() { |
| 3303 assertBool(this); |
| 3304 return BoolState.TRUE_STATE; |
| 3305 } |
| 3306 |
| 3307 /** |
| 3308 * Return the result of invoking the '||' operator on this object with the giv
en argument. |
| 3309 * |
| 3310 * @param rightOperand the right-hand operand of the operation |
| 3311 * @return the result of invoking the '||' operator on this object with the gi
ven argument |
| 3312 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3313 */ |
| 3314 BoolState logicalOr(InstanceState rightOperand) { |
| 3315 assertBool(this); |
| 3316 assertBool(rightOperand); |
| 3317 return rightOperand.convertToBool(); |
| 3318 } |
| 3319 |
| 3320 /** |
| 3321 * Return the result of invoking the '-' operator on this object with the give
n argument. |
| 3322 * |
| 3323 * @param rightOperand the right-hand operand of the operation |
| 3324 * @return the result of invoking the '-' operator on this object with the giv
en argument |
| 3325 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3326 */ |
| 3327 NumState minus(InstanceState rightOperand) { |
| 3328 assertNumOrNull(this); |
| 3329 assertNumOrNull(rightOperand); |
| 3330 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3331 } |
| 3332 |
| 3333 /** |
| 3334 * Return the result of invoking the '-' operator on this object. |
| 3335 * |
| 3336 * @return the result of invoking the '-' operator on this object |
| 3337 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3338 */ |
| 3339 NumState negated() { |
| 3340 assertNumOrNull(this); |
| 3341 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3342 } |
| 3343 |
| 3344 /** |
| 3345 * Return the result of invoking the '%' operator on this object with the give
n argument. |
| 3346 * |
| 3347 * @param rightOperand the right-hand operand of the operation |
| 3348 * @return the result of invoking the '%' operator on this object with the giv
en argument |
| 3349 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3350 */ |
| 3351 NumState remainder(InstanceState rightOperand) { |
| 3352 assertNumOrNull(this); |
| 3353 assertNumOrNull(rightOperand); |
| 3354 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3355 } |
| 3356 |
| 3357 /** |
| 3358 * Return the result of invoking the '<<' operator on this object with t
he given argument. |
| 3359 * |
| 3360 * @param rightOperand the right-hand operand of the operation |
| 3361 * @return the result of invoking the '<<' operator on this object with
the given argument |
| 3362 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3363 */ |
| 3364 IntState shiftLeft(InstanceState rightOperand) { |
| 3365 assertIntOrNull(this); |
| 3366 assertIntOrNull(rightOperand); |
| 3367 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3368 } |
| 3369 |
| 3370 /** |
| 3371 * Return the result of invoking the '>>' operator on this object with t
he given argument. |
| 3372 * |
| 3373 * @param rightOperand the right-hand operand of the operation |
| 3374 * @return the result of invoking the '>>' operator on this object with
the given argument |
| 3375 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3376 */ |
| 3377 IntState shiftRight(InstanceState rightOperand) { |
| 3378 assertIntOrNull(this); |
| 3379 assertIntOrNull(rightOperand); |
| 3380 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3381 } |
| 3382 |
| 3383 /** |
| 3384 * Return the result of invoking the '*' operator on this object with the give
n argument. |
| 3385 * |
| 3386 * @param rightOperand the right-hand operand of the operation |
| 3387 * @return the result of invoking the '*' operator on this object with the giv
en argument |
| 3388 * @throws EvaluationException if the operator is not appropriate for an objec
t of this kind |
| 3389 */ |
| 3390 NumState times(InstanceState rightOperand) { |
| 3391 assertNumOrNull(this); |
| 3392 assertNumOrNull(rightOperand); |
| 3393 throw new EvaluationException(CompileTimeErrorCode.INVALID_CONSTANT); |
| 3394 } |
| 3395 |
| 3396 /** |
| 3397 * Throw an exception if the given state does not represent a boolean value. |
| 3398 * |
| 3399 * @param state the state being tested |
| 3400 * @throws EvaluationException if the given state does not represent a boolean
value |
| 3401 */ |
| 3402 void assertBool(InstanceState state) { |
| 3403 if (!(state is BoolState || state is DynamicState)) { |
| 3404 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL); |
| 3405 } |
| 3406 } |
| 3407 |
| 3408 /** |
| 3409 * Throw an exception if the given state does not represent a boolean, numeric
, string or null |
| 3410 * value. |
| 3411 * |
| 3412 * @param state the state being tested |
| 3413 * @throws EvaluationException if the given state does not represent a boolean
, numeric, string or |
| 3414 * null value |
| 3415 */ |
| 3416 void assertBoolNumStringOrNull(InstanceState state) { |
| 3417 if (!(state is BoolState || state is DoubleState || state is IntState || sta
te is NumState || state is StringState || state is NullState || state is Dynamic
State)) { |
| 3418 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NU
M_STRING); |
| 3419 } |
| 3420 } |
| 3421 |
| 3422 /** |
| 3423 * Throw an exception if the given state does not represent an integer or null
value. |
| 3424 * |
| 3425 * @param state the state being tested |
| 3426 * @throws EvaluationException if the given state does not represent an intege
r or null value |
| 3427 */ |
| 3428 void assertIntOrNull(InstanceState state) { |
| 3429 if (!(state is IntState || state is NumState || state is NullState || state
is DynamicState)) { |
| 3430 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_INT); |
| 3431 } |
| 3432 } |
| 3433 |
| 3434 /** |
| 3435 * Throw an exception if the given state does not represent a boolean, numeric
, string or null |
| 3436 * value. |
| 3437 * |
| 3438 * @param state the state being tested |
| 3439 * @throws EvaluationException if the given state does not represent a boolean
, numeric, string or |
| 3440 * null value |
| 3441 */ |
| 3442 void assertNumOrNull(InstanceState state) { |
| 3443 if (!(state is DoubleState || state is IntState || state is NumState || stat
e is NullState || state is DynamicState)) { |
| 3444 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); |
| 3445 } |
| 3446 } |
| 3447 |
| 3448 /** |
| 3449 * Throw an exception if the given state does not represent a String value. |
| 3450 * |
| 3451 * @param state the state being tested |
| 3452 * @throws EvaluationException if the given state does not represent a String
value |
| 3453 */ |
| 3454 void assertString(InstanceState state) { |
| 3455 if (!(state is StringState || state is DynamicState)) { |
| 3456 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL); |
| 3457 } |
| 3458 } |
| 3459 } |
| 3460 |
| 3461 /** |
| 3462 * Instances of the class `IntState` represent the state of an object representi
ng an int. |
| 3463 */ |
| 3464 class IntState extends NumState { |
| 3465 /** |
| 3466 * The value of this instance. |
| 3467 */ |
| 3468 final int value; |
| 3469 |
| 3470 /** |
| 3471 * A state that can be used to represent an int whose value is not known. |
| 3472 */ |
| 3473 static IntState UNKNOWN_VALUE = new IntState(null); |
| 3474 |
| 3475 /** |
| 3476 * Initialize a newly created state to represent an int with the given value. |
| 3477 * |
| 3478 * @param value the value of this instance |
| 3479 */ |
| 3480 IntState(this.value); |
| 3481 |
| 3482 @override |
| 3483 NumState add(InstanceState rightOperand) { |
| 3484 assertNumOrNull(rightOperand); |
| 3485 if (value == null) { |
| 3486 if (rightOperand is DoubleState) { |
| 3487 return DoubleState.UNKNOWN_VALUE; |
| 3488 } |
| 3489 return UNKNOWN_VALUE; |
| 3490 } |
| 3491 if (rightOperand is IntState) { |
| 3492 int rightValue = rightOperand.value; |
| 3493 if (rightValue == null) { |
| 3494 return UNKNOWN_VALUE; |
| 3495 } |
| 3496 return new IntState(value + rightValue); |
| 3497 } else if (rightOperand is DoubleState) { |
| 3498 double rightValue = rightOperand.value; |
| 3499 if (rightValue == null) { |
| 3500 return DoubleState.UNKNOWN_VALUE; |
| 3501 } |
| 3502 return new DoubleState(value.toDouble() + rightValue); |
| 3503 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3504 return UNKNOWN_VALUE; |
| 3505 } |
| 3506 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3507 } |
| 3508 |
| 3509 @override |
| 3510 IntState bitAnd(InstanceState rightOperand) { |
| 3511 assertIntOrNull(rightOperand); |
| 3512 if (value == null) { |
| 3513 return UNKNOWN_VALUE; |
| 3514 } |
| 3515 if (rightOperand is IntState) { |
| 3516 int rightValue = rightOperand.value; |
| 3517 if (rightValue == null) { |
| 3518 return UNKNOWN_VALUE; |
| 3519 } |
| 3520 return new IntState(value & rightValue); |
| 3521 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3522 return UNKNOWN_VALUE; |
| 3523 } |
| 3524 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3525 } |
| 3526 |
| 3527 @override |
| 3528 IntState bitNot() { |
| 3529 if (value == null) { |
| 3530 return UNKNOWN_VALUE; |
| 3531 } |
| 3532 return new IntState(~value); |
| 3533 } |
| 3534 |
| 3535 @override |
| 3536 IntState bitOr(InstanceState rightOperand) { |
| 3537 assertIntOrNull(rightOperand); |
| 3538 if (value == null) { |
| 3539 return UNKNOWN_VALUE; |
| 3540 } |
| 3541 if (rightOperand is IntState) { |
| 3542 int rightValue = rightOperand.value; |
| 3543 if (rightValue == null) { |
| 3544 return UNKNOWN_VALUE; |
| 3545 } |
| 3546 return new IntState(value | rightValue); |
| 3547 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3548 return UNKNOWN_VALUE; |
| 3549 } |
| 3550 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3551 } |
| 3552 |
| 3553 @override |
| 3554 IntState bitXor(InstanceState rightOperand) { |
| 3555 assertIntOrNull(rightOperand); |
| 3556 if (value == null) { |
| 3557 return UNKNOWN_VALUE; |
| 3558 } |
| 3559 if (rightOperand is IntState) { |
| 3560 int rightValue = rightOperand.value; |
| 3561 if (rightValue == null) { |
| 3562 return UNKNOWN_VALUE; |
| 3563 } |
| 3564 return new IntState(value ^ rightValue); |
| 3565 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3566 return UNKNOWN_VALUE; |
| 3567 } |
| 3568 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3569 } |
| 3570 |
| 3571 @override |
| 3572 StringState convertToString() { |
| 3573 if (value == null) { |
| 3574 return StringState.UNKNOWN_VALUE; |
| 3575 } |
| 3576 return new StringState(value.toString()); |
| 3577 } |
| 3578 |
| 3579 @override |
| 3580 NumState divide(InstanceState rightOperand) { |
| 3581 assertNumOrNull(rightOperand); |
| 3582 if (value == null) { |
| 3583 if (rightOperand is DoubleState) { |
| 3584 return DoubleState.UNKNOWN_VALUE; |
| 3585 } |
| 3586 return UNKNOWN_VALUE; |
| 3587 } |
| 3588 if (rightOperand is IntState) { |
| 3589 int rightValue = rightOperand.value; |
| 3590 if (rightValue == null) { |
| 3591 return UNKNOWN_VALUE; |
| 3592 } else if (rightValue == 0) { |
| 3593 return new DoubleState(value.toDouble() / rightValue.toDouble()); |
| 3594 } |
| 3595 return new IntState(value ~/ rightValue); |
| 3596 } else if (rightOperand is DoubleState) { |
| 3597 double rightValue = rightOperand.value; |
| 3598 if (rightValue == null) { |
| 3599 return DoubleState.UNKNOWN_VALUE; |
| 3600 } |
| 3601 return new DoubleState(value.toDouble() / rightValue); |
| 3602 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3603 return UNKNOWN_VALUE; |
| 3604 } |
| 3605 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3606 } |
| 3607 |
| 3608 @override |
| 3609 BoolState equalEqual(InstanceState rightOperand) { |
| 3610 assertBoolNumStringOrNull(rightOperand); |
| 3611 if (value == null) { |
| 3612 return BoolState.UNKNOWN_VALUE; |
| 3613 } |
| 3614 if (rightOperand is IntState) { |
| 3615 int rightValue = rightOperand.value; |
| 3616 if (rightValue == null) { |
| 3617 return BoolState.UNKNOWN_VALUE; |
| 3618 } |
| 3619 return BoolState.from(value == rightValue); |
| 3620 } else if (rightOperand is DoubleState) { |
| 3621 double rightValue = rightOperand.value; |
| 3622 if (rightValue == null) { |
| 3623 return BoolState.UNKNOWN_VALUE; |
| 3624 } |
| 3625 return BoolState.from(rightValue == value.toDouble()); |
| 3626 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3627 return BoolState.UNKNOWN_VALUE; |
| 3628 } |
| 3629 return BoolState.FALSE_STATE; |
| 3630 } |
| 3631 |
| 3632 @override |
| 3633 bool operator ==(Object object) => object is IntState && (value == object.valu
e); |
| 3634 |
| 3635 @override |
| 3636 String get typeName => "int"; |
| 3637 |
| 3638 @override |
| 3639 BoolState greaterThan(InstanceState rightOperand) { |
| 3640 assertNumOrNull(rightOperand); |
| 3641 if (value == null) { |
| 3642 return BoolState.UNKNOWN_VALUE; |
| 3643 } |
| 3644 if (rightOperand is IntState) { |
| 3645 int rightValue = rightOperand.value; |
| 3646 if (rightValue == null) { |
| 3647 return BoolState.UNKNOWN_VALUE; |
| 3648 } |
| 3649 return BoolState.from(value.compareTo(rightValue) > 0); |
| 3650 } else if (rightOperand is DoubleState) { |
| 3651 double rightValue = rightOperand.value; |
| 3652 if (rightValue == null) { |
| 3653 return BoolState.UNKNOWN_VALUE; |
| 3654 } |
| 3655 return BoolState.from(value.toDouble() > rightValue); |
| 3656 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3657 return BoolState.UNKNOWN_VALUE; |
| 3658 } |
| 3659 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3660 } |
| 3661 |
| 3662 @override |
| 3663 BoolState greaterThanOrEqual(InstanceState rightOperand) { |
| 3664 assertNumOrNull(rightOperand); |
| 3665 if (value == null) { |
| 3666 return BoolState.UNKNOWN_VALUE; |
| 3667 } |
| 3668 if (rightOperand is IntState) { |
| 3669 int rightValue = rightOperand.value; |
| 3670 if (rightValue == null) { |
| 3671 return BoolState.UNKNOWN_VALUE; |
| 3672 } |
| 3673 return BoolState.from(value.compareTo(rightValue) >= 0); |
| 3674 } else if (rightOperand is DoubleState) { |
| 3675 double rightValue = rightOperand.value; |
| 3676 if (rightValue == null) { |
| 3677 return BoolState.UNKNOWN_VALUE; |
| 3678 } |
| 3679 return BoolState.from(value.toDouble() >= rightValue); |
| 3680 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3681 return BoolState.UNKNOWN_VALUE; |
| 3682 } |
| 3683 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3684 } |
| 3685 |
| 3686 @override |
| 3687 bool get hasExactValue => true; |
| 3688 |
| 3689 @override |
| 3690 int get hashCode => value == null ? 0 : value.hashCode; |
| 3691 |
| 3692 @override |
| 3693 IntState integerDivide(InstanceState rightOperand) { |
| 3694 assertNumOrNull(rightOperand); |
| 3695 if (value == null) { |
| 3696 return UNKNOWN_VALUE; |
| 3697 } |
| 3698 if (rightOperand is IntState) { |
| 3699 int rightValue = rightOperand.value; |
| 3700 if (rightValue == null) { |
| 3701 return UNKNOWN_VALUE; |
| 3702 } else if (rightValue == 0) { |
| 3703 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_IDB
ZE); |
| 3704 } |
| 3705 return new IntState(value ~/ rightValue); |
| 3706 } else if (rightOperand is DoubleState) { |
| 3707 double rightValue = rightOperand.value; |
| 3708 if (rightValue == null) { |
| 3709 return UNKNOWN_VALUE; |
| 3710 } |
| 3711 double result = value.toDouble() / rightValue; |
| 3712 return new IntState(result.toInt()); |
| 3713 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3714 return UNKNOWN_VALUE; |
| 3715 } |
| 3716 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3717 } |
| 3718 |
| 3719 @override |
| 3720 bool get isBoolNumStringOrNull => true; |
| 3721 |
| 3722 @override |
| 3723 bool get isUnknown => value == null; |
| 3724 |
| 3725 @override |
| 3726 BoolState lessThan(InstanceState rightOperand) { |
| 3727 assertNumOrNull(rightOperand); |
| 3728 if (value == null) { |
| 3729 return BoolState.UNKNOWN_VALUE; |
| 3730 } |
| 3731 if (rightOperand is IntState) { |
| 3732 int rightValue = rightOperand.value; |
| 3733 if (rightValue == null) { |
| 3734 return BoolState.UNKNOWN_VALUE; |
| 3735 } |
| 3736 return BoolState.from(value.compareTo(rightValue) < 0); |
| 3737 } else if (rightOperand is DoubleState) { |
| 3738 double rightValue = rightOperand.value; |
| 3739 if (rightValue == null) { |
| 3740 return BoolState.UNKNOWN_VALUE; |
| 3741 } |
| 3742 return BoolState.from(value.toDouble() < rightValue); |
| 3743 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3744 return BoolState.UNKNOWN_VALUE; |
| 3745 } |
| 3746 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3747 } |
| 3748 |
| 3749 @override |
| 3750 BoolState lessThanOrEqual(InstanceState rightOperand) { |
| 3751 assertNumOrNull(rightOperand); |
| 3752 if (value == null) { |
| 3753 return BoolState.UNKNOWN_VALUE; |
| 3754 } |
| 3755 if (rightOperand is IntState) { |
| 3756 int rightValue = rightOperand.value; |
| 3757 if (rightValue == null) { |
| 3758 return BoolState.UNKNOWN_VALUE; |
| 3759 } |
| 3760 return BoolState.from(value.compareTo(rightValue) <= 0); |
| 3761 } else if (rightOperand is DoubleState) { |
| 3762 double rightValue = rightOperand.value; |
| 3763 if (rightValue == null) { |
| 3764 return BoolState.UNKNOWN_VALUE; |
| 3765 } |
| 3766 return BoolState.from(value.toDouble() <= rightValue); |
| 3767 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3768 return BoolState.UNKNOWN_VALUE; |
| 3769 } |
| 3770 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3771 } |
| 3772 |
| 3773 @override |
| 3774 NumState minus(InstanceState rightOperand) { |
| 3775 assertNumOrNull(rightOperand); |
| 3776 if (value == null) { |
| 3777 if (rightOperand is DoubleState) { |
| 3778 return DoubleState.UNKNOWN_VALUE; |
| 3779 } |
| 3780 return UNKNOWN_VALUE; |
| 3781 } |
| 3782 if (rightOperand is IntState) { |
| 3783 int rightValue = rightOperand.value; |
| 3784 if (rightValue == null) { |
| 3785 return UNKNOWN_VALUE; |
| 3786 } |
| 3787 return new IntState(value - rightValue); |
| 3788 } else if (rightOperand is DoubleState) { |
| 3789 double rightValue = rightOperand.value; |
| 3790 if (rightValue == null) { |
| 3791 return DoubleState.UNKNOWN_VALUE; |
| 3792 } |
| 3793 return new DoubleState(value.toDouble() - rightValue); |
| 3794 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3795 return UNKNOWN_VALUE; |
| 3796 } |
| 3797 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3798 } |
| 3799 |
| 3800 @override |
| 3801 NumState negated() { |
| 3802 if (value == null) { |
| 3803 return UNKNOWN_VALUE; |
| 3804 } |
| 3805 return new IntState(-value); |
| 3806 } |
| 3807 |
| 3808 @override |
| 3809 NumState remainder(InstanceState rightOperand) { |
| 3810 assertNumOrNull(rightOperand); |
| 3811 if (value == null) { |
| 3812 if (rightOperand is DoubleState) { |
| 3813 return DoubleState.UNKNOWN_VALUE; |
| 3814 } |
| 3815 return UNKNOWN_VALUE; |
| 3816 } |
| 3817 if (rightOperand is IntState) { |
| 3818 int rightValue = rightOperand.value; |
| 3819 if (rightValue == null) { |
| 3820 return UNKNOWN_VALUE; |
| 3821 } else if (rightValue == 0) { |
| 3822 return new DoubleState(value.toDouble() % rightValue.toDouble()); |
| 3823 } |
| 3824 return new IntState(value.remainder(rightValue)); |
| 3825 } else if (rightOperand is DoubleState) { |
| 3826 double rightValue = rightOperand.value; |
| 3827 if (rightValue == null) { |
| 3828 return DoubleState.UNKNOWN_VALUE; |
| 3829 } |
| 3830 return new DoubleState(value.toDouble() % rightValue); |
| 3831 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3832 return UNKNOWN_VALUE; |
| 3833 } |
| 3834 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3835 } |
| 3836 |
| 3837 @override |
| 3838 IntState shiftLeft(InstanceState rightOperand) { |
| 3839 assertIntOrNull(rightOperand); |
| 3840 if (value == null) { |
| 3841 return UNKNOWN_VALUE; |
| 3842 } |
| 3843 if (rightOperand is IntState) { |
| 3844 int rightValue = rightOperand.value; |
| 3845 if (rightValue == null) { |
| 3846 return UNKNOWN_VALUE; |
| 3847 } else if (rightValue.bitLength > 31) { |
| 3848 return UNKNOWN_VALUE; |
| 3849 } |
| 3850 return new IntState(value << rightValue); |
| 3851 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3852 return UNKNOWN_VALUE; |
| 3853 } |
| 3854 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3855 } |
| 3856 |
| 3857 @override |
| 3858 IntState shiftRight(InstanceState rightOperand) { |
| 3859 assertIntOrNull(rightOperand); |
| 3860 if (value == null) { |
| 3861 return UNKNOWN_VALUE; |
| 3862 } |
| 3863 if (rightOperand is IntState) { |
| 3864 int rightValue = rightOperand.value; |
| 3865 if (rightValue == null) { |
| 3866 return UNKNOWN_VALUE; |
| 3867 } else if (rightValue.bitLength > 31) { |
| 3868 return UNKNOWN_VALUE; |
| 3869 } |
| 3870 return new IntState(value >> rightValue); |
| 3871 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3872 return UNKNOWN_VALUE; |
| 3873 } |
| 3874 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3875 } |
| 3876 |
| 3877 @override |
| 3878 NumState times(InstanceState rightOperand) { |
| 3879 assertNumOrNull(rightOperand); |
| 3880 if (value == null) { |
| 3881 if (rightOperand is DoubleState) { |
| 3882 return DoubleState.UNKNOWN_VALUE; |
| 3883 } |
| 3884 return UNKNOWN_VALUE; |
| 3885 } |
| 3886 if (rightOperand is IntState) { |
| 3887 int rightValue = rightOperand.value; |
| 3888 if (rightValue == null) { |
| 3889 return UNKNOWN_VALUE; |
| 3890 } |
| 3891 return new IntState(value * rightValue); |
| 3892 } else if (rightOperand is DoubleState) { |
| 3893 double rightValue = rightOperand.value; |
| 3894 if (rightValue == null) { |
| 3895 return DoubleState.UNKNOWN_VALUE; |
| 3896 } |
| 3897 return new DoubleState(value.toDouble() * rightValue); |
| 3898 } else if (rightOperand is DynamicState || rightOperand is NumState) { |
| 3899 return UNKNOWN_VALUE; |
| 3900 } |
| 3901 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 3902 } |
| 3903 |
| 3904 @override |
| 3905 String toString() => value == null ? "-unknown-" : value.toString(); |
| 3906 } |
| 3907 |
| 3908 /** |
| 3909 * The unique instance of the class `ListState` represents the state of an objec
t representing |
| 3910 * a list. |
| 3911 */ |
| 3912 class ListState extends InstanceState { |
| 3913 /** |
| 3914 * The elements of the list. |
| 3915 */ |
| 3916 final List<DartObjectImpl> _elements; |
| 3917 |
| 3918 /** |
| 3919 * Initialize a newly created state to represent a list with the given element
s. |
| 3920 * |
| 3921 * @param elements the elements of the list |
| 3922 */ |
| 3923 ListState(this._elements); |
| 3924 |
| 3925 @override |
| 3926 StringState convertToString() => StringState.UNKNOWN_VALUE; |
| 3927 |
| 3928 @override |
| 3929 BoolState equalEqual(InstanceState rightOperand) { |
| 3930 assertBoolNumStringOrNull(rightOperand); |
| 3931 if (rightOperand is DynamicState) { |
| 3932 return BoolState.UNKNOWN_VALUE; |
| 3933 } |
| 3934 return BoolState.from(this == rightOperand); |
| 3935 } |
| 3936 |
| 3937 @override |
| 3938 bool operator ==(Object object) { |
| 3939 if (object is! ListState) { |
| 3940 return false; |
| 3941 } |
| 3942 List<DartObjectImpl> otherElements = (object as ListState)._elements; |
| 3943 int count = _elements.length; |
| 3944 if (otherElements.length != count) { |
| 3945 return false; |
| 3946 } else if (count == 0) { |
| 3947 return true; |
| 3948 } |
| 3949 for (int i = 0; i < count; i++) { |
| 3950 if (_elements[i] != otherElements[i]) { |
| 3951 return false; |
| 3952 } |
| 3953 } |
| 3954 return true; |
| 3955 } |
| 3956 |
| 3957 @override |
| 3958 String get typeName => "List"; |
| 3959 |
| 3960 @override |
| 3961 List<Object> get value { |
| 3962 int count = _elements.length; |
| 3963 List<Object> result = new List<Object>(count); |
| 3964 for (int i = 0; i < count; i++) { |
| 3965 DartObjectImpl element = _elements[i]; |
| 3966 if (!element.hasExactValue) { |
| 3967 return null; |
| 3968 } |
| 3969 result[i] = element.value; |
| 3970 } |
| 3971 return result; |
| 3972 } |
| 3973 |
| 3974 @override |
| 3975 bool get hasExactValue { |
| 3976 int count = _elements.length; |
| 3977 for (int i = 0; i < count; i++) { |
| 3978 if (!_elements[i].hasExactValue) { |
| 3979 return false; |
| 3980 } |
| 3981 } |
| 3982 return true; |
| 3983 } |
| 3984 |
| 3985 @override |
| 3986 int get hashCode { |
| 3987 int value = 0; |
| 3988 int count = _elements.length; |
| 3989 for (int i = 0; i < count; i++) { |
| 3990 value = (value << 3) ^ _elements[i].hashCode; |
| 3991 } |
| 3992 return value; |
| 3993 } |
| 3994 } |
| 3995 |
| 3996 /** |
| 3997 * The unique instance of the class `ListState` represents the state of an objec
t representing |
| 3998 * a map. |
| 3999 */ |
| 4000 class MapState extends InstanceState { |
| 4001 /** |
| 4002 * The entries in the map. |
| 4003 */ |
| 4004 final HashMap<DartObjectImpl, DartObjectImpl> _entries; |
| 4005 |
| 4006 /** |
| 4007 * Initialize a newly created state to represent a map with the given entries. |
| 4008 * |
| 4009 * @param entries the entries in the map |
| 4010 */ |
| 4011 MapState(this._entries); |
| 4012 |
| 4013 @override |
| 4014 StringState convertToString() => StringState.UNKNOWN_VALUE; |
| 4015 |
| 4016 @override |
| 4017 BoolState equalEqual(InstanceState rightOperand) { |
| 4018 assertBoolNumStringOrNull(rightOperand); |
| 4019 if (rightOperand is DynamicState) { |
| 4020 return BoolState.UNKNOWN_VALUE; |
| 4021 } |
| 4022 return BoolState.from(this == rightOperand); |
| 4023 } |
| 4024 |
| 4025 @override |
| 4026 bool operator ==(Object object) { |
| 4027 if (object is! MapState) { |
| 4028 return false; |
| 4029 } |
| 4030 HashMap<DartObjectImpl, DartObjectImpl> otherElements = (object as MapState)
._entries; |
| 4031 int count = _entries.length; |
| 4032 if (otherElements.length != count) { |
| 4033 return false; |
| 4034 } else if (count == 0) { |
| 4035 return true; |
| 4036 } |
| 4037 for (MapEntry<DartObjectImpl, DartObjectImpl> entry in getMapEntrySet(_entri
es)) { |
| 4038 DartObjectImpl key = entry.getKey(); |
| 4039 DartObjectImpl value = entry.getValue(); |
| 4040 DartObjectImpl otherValue = otherElements[key]; |
| 4041 if (value != otherValue) { |
| 4042 return false; |
| 4043 } |
| 4044 } |
| 4045 return true; |
| 4046 } |
| 4047 |
| 4048 @override |
| 4049 String get typeName => "Map"; |
| 4050 |
| 4051 @override |
| 4052 Map<Object, Object> get value { |
| 4053 HashMap<Object, Object> result = new HashMap<Object, Object>(); |
| 4054 for (MapEntry<DartObjectImpl, DartObjectImpl> entry in getMapEntrySet(_entri
es)) { |
| 4055 DartObjectImpl key = entry.getKey(); |
| 4056 DartObjectImpl value = entry.getValue(); |
| 4057 if (!key.hasExactValue || !value.hasExactValue) { |
| 4058 return null; |
| 4059 } |
| 4060 result[key.value] = value.value; |
| 4061 } |
| 4062 return result; |
| 4063 } |
| 4064 |
| 4065 @override |
| 4066 bool get hasExactValue { |
| 4067 for (MapEntry<DartObjectImpl, DartObjectImpl> entry in getMapEntrySet(_entri
es)) { |
| 4068 if (!entry.getKey().hasExactValue || !entry.getValue().hasExactValue) { |
| 4069 return false; |
| 4070 } |
| 4071 } |
| 4072 return true; |
| 4073 } |
| 4074 |
| 4075 @override |
| 4076 int get hashCode { |
| 4077 int value = 0; |
| 4078 for (DartObjectImpl key in _entries.keys.toSet()) { |
| 4079 value = (value << 3) ^ key.hashCode; |
| 4080 } |
| 4081 return value; |
| 4082 } |
| 4083 } |
| 4084 |
| 4085 /** |
| 4086 * The unique instance of the class `NullState` represents the state of the valu
e 'null'. |
| 4087 */ |
| 4088 class NullState extends InstanceState { |
| 4089 /** |
| 4090 * An instance representing the boolean value 'true'. |
| 4091 */ |
| 4092 static NullState NULL_STATE = new NullState(); |
| 4093 |
| 4094 @override |
| 4095 BoolState convertToBool() { |
| 4096 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 4097 } |
| 4098 |
| 4099 @override |
| 4100 StringState convertToString() => new StringState("null"); |
| 4101 |
| 4102 @override |
| 4103 BoolState equalEqual(InstanceState rightOperand) { |
| 4104 assertBoolNumStringOrNull(rightOperand); |
| 4105 if (rightOperand is DynamicState) { |
| 4106 return BoolState.UNKNOWN_VALUE; |
| 4107 } |
| 4108 return BoolState.from(rightOperand is NullState); |
| 4109 } |
| 4110 |
| 4111 @override |
| 4112 bool operator ==(Object object) => object is NullState; |
| 4113 |
| 4114 @override |
| 4115 String get typeName => "Null"; |
| 4116 |
| 4117 @override |
| 4118 bool get hasExactValue => true; |
| 4119 |
| 4120 @override |
| 4121 int get hashCode => 0; |
| 4122 |
| 4123 @override |
| 4124 bool get isBoolNumStringOrNull => true; |
| 4125 |
| 4126 @override |
| 4127 BoolState logicalNot() { |
| 4128 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTI
ON); |
| 4129 } |
| 4130 |
| 4131 @override |
| 4132 String toString() => "null"; |
| 4133 } |
| 4134 |
| 4135 /** |
| 4136 * Instances of the class `NumState` represent the state of an object representi
ng a number of |
| 4137 * an unknown type (a 'num'). |
| 4138 */ |
| 4139 class NumState extends InstanceState { |
| 4140 /** |
| 4141 * A state that can be used to represent a number whose value is not known. |
| 4142 */ |
| 4143 static NumState UNKNOWN_VALUE = new NumState(); |
| 4144 |
| 4145 @override |
| 4146 NumState add(InstanceState rightOperand) { |
| 4147 assertNumOrNull(rightOperand); |
| 4148 return UNKNOWN_VALUE; |
| 4149 } |
| 4150 |
| 4151 @override |
| 4152 StringState convertToString() => StringState.UNKNOWN_VALUE; |
| 4153 |
| 4154 @override |
| 4155 NumState divide(InstanceState rightOperand) { |
| 4156 assertNumOrNull(rightOperand); |
| 4157 return UNKNOWN_VALUE; |
| 4158 } |
| 4159 |
| 4160 @override |
| 4161 BoolState equalEqual(InstanceState rightOperand) { |
| 4162 assertBoolNumStringOrNull(rightOperand); |
| 4163 return BoolState.UNKNOWN_VALUE; |
| 4164 } |
| 4165 |
| 4166 @override |
| 4167 bool operator ==(Object object) => object is NumState; |
| 4168 |
| 4169 @override |
| 4170 String get typeName => "num"; |
| 4171 |
| 4172 @override |
| 4173 BoolState greaterThan(InstanceState rightOperand) { |
| 4174 assertNumOrNull(rightOperand); |
| 4175 return BoolState.UNKNOWN_VALUE; |
| 4176 } |
| 4177 |
| 4178 @override |
| 4179 BoolState greaterThanOrEqual(InstanceState rightOperand) { |
| 4180 assertNumOrNull(rightOperand); |
| 4181 return BoolState.UNKNOWN_VALUE; |
| 4182 } |
| 4183 |
| 4184 @override |
| 4185 int get hashCode => 7; |
| 4186 |
| 4187 @override |
| 4188 IntState integerDivide(InstanceState rightOperand) { |
| 4189 assertNumOrNull(rightOperand); |
| 4190 if (rightOperand is IntState) { |
| 4191 int rightValue = rightOperand.value; |
| 4192 if (rightValue == null) { |
| 4193 return IntState.UNKNOWN_VALUE; |
| 4194 } else if (rightValue == 0) { |
| 4195 throw new EvaluationException(CompileTimeErrorCode.CONST_EVAL_THROWS_IDB
ZE); |
| 4196 } |
| 4197 } else if (rightOperand is DynamicState) { |
| 4198 return IntState.UNKNOWN_VALUE; |
| 4199 } |
| 4200 return IntState.UNKNOWN_VALUE; |
| 4201 } |
| 4202 |
| 4203 @override |
| 4204 bool get isBoolNumStringOrNull => true; |
| 4205 |
| 4206 @override |
| 4207 bool get isUnknown => identical(this, UNKNOWN_VALUE); |
| 4208 |
| 4209 @override |
| 4210 BoolState lessThan(InstanceState rightOperand) { |
| 4211 assertNumOrNull(rightOperand); |
| 4212 return BoolState.UNKNOWN_VALUE; |
| 4213 } |
| 4214 |
| 4215 @override |
| 4216 BoolState lessThanOrEqual(InstanceState rightOperand) { |
| 4217 assertNumOrNull(rightOperand); |
| 4218 return BoolState.UNKNOWN_VALUE; |
| 4219 } |
| 4220 |
| 4221 @override |
| 4222 NumState minus(InstanceState rightOperand) { |
| 4223 assertNumOrNull(rightOperand); |
| 4224 return UNKNOWN_VALUE; |
| 4225 } |
| 4226 |
| 4227 @override |
| 4228 NumState negated() => UNKNOWN_VALUE; |
| 4229 |
| 4230 @override |
| 4231 NumState remainder(InstanceState rightOperand) { |
| 4232 assertNumOrNull(rightOperand); |
| 4233 return UNKNOWN_VALUE; |
| 4234 } |
| 4235 |
| 4236 @override |
| 4237 NumState times(InstanceState rightOperand) { |
| 4238 assertNumOrNull(rightOperand); |
| 4239 return UNKNOWN_VALUE; |
| 4240 } |
| 4241 |
| 4242 @override |
| 4243 String toString() => "-unknown-"; |
| 4244 } |
| 4245 |
| 4246 /** |
| 4247 * Instances of the class `ReferenceFinder` add reference information for a give
n variable to |
| 4248 * the bi-directional mapping used to order the evaluation of constants. |
| 4249 */ |
| 4250 class ReferenceFinder extends RecursiveAstVisitor<Object> { |
| 4251 /** |
| 4252 * The element representing the construct that will be visited. |
| 4253 */ |
| 4254 final AstNode _source; |
| 4255 |
| 4256 /** |
| 4257 * A graph in which the nodes are the constant variables and the edges are fro
m each variable to |
| 4258 * the other constant variables that are referenced in the head's initializer. |
| 4259 */ |
| 4260 final DirectedGraph<AstNode> _referenceGraph; |
| 4261 |
| 4262 /** |
| 4263 * A table mapping constant variables to the declarations of those variables. |
| 4264 */ |
| 4265 final HashMap<VariableElement, VariableDeclaration> _variableDeclarationMap; |
| 4266 |
| 4267 /** |
| 4268 * A table mapping constant constructors to the declarations of those construc
tors. |
| 4269 */ |
| 4270 final HashMap<ConstructorElement, ConstructorDeclaration> _constructorDeclarat
ionMap; |
| 4271 |
| 4272 /** |
| 4273 * Initialize a newly created reference finder to find references from the giv
en variable to other |
| 4274 * variables and to add those references to the given graph. |
| 4275 * |
| 4276 * @param source the element representing the variable whose initializer will
be visited |
| 4277 * @param referenceGraph a graph recording which variables (heads) reference w
hich other variables |
| 4278 * (tails) in their initializers |
| 4279 * @param variableDeclarationMap A table mapping constant variables to the dec
larations of those |
| 4280 * variables. |
| 4281 * @param constructorDeclarationMap A table mapping constant constructors to t
he declarations of |
| 4282 * those constructors. |
| 4283 */ |
| 4284 ReferenceFinder(this._source, this._referenceGraph, this._variableDeclarationM
ap, this._constructorDeclarationMap); |
| 4285 |
| 4286 @override |
| 4287 Object visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 4288 if (node.isConst) { |
| 4289 _referenceGraph.addEdge(_source, node); |
| 4290 } |
| 4291 return null; |
| 4292 } |
| 4293 |
| 4294 @override |
| 4295 Object visitSimpleIdentifier(SimpleIdentifier node) { |
| 4296 Element element = node.staticElement; |
| 4297 if (element is PropertyAccessorElement) { |
| 4298 element = (element as PropertyAccessorElement).variable; |
| 4299 } |
| 4300 if (element is VariableElement) { |
| 4301 VariableElement variable = element as VariableElement; |
| 4302 if (variable.isConst) { |
| 4303 VariableDeclaration variableDeclaration = _variableDeclarationMap[variab
le]; |
| 4304 // The declaration will be null when the variable is not defined in the
compilation units |
| 4305 // that were used to produce the variableDeclarationMap. In such cases,
the variable should |
| 4306 // already have a value associated with it, but we don't bother to check
because there's |
| 4307 // nothing we can do about it at this point. |
| 4308 if (variableDeclaration != null) { |
| 4309 _referenceGraph.addEdge(_source, variableDeclaration); |
| 4310 } |
| 4311 } |
| 4312 } |
| 4313 return null; |
| 4314 } |
| 4315 |
| 4316 @override |
| 4317 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| 4318 super.visitSuperConstructorInvocation(node); |
| 4319 ConstructorElement constructor = node.staticElement; |
| 4320 if (constructor != null && constructor.isConst) { |
| 4321 ConstructorDeclaration constructorDeclaration = _constructorDeclarationMap
[constructor]; |
| 4322 // The declaration will be null when the constructor is not defined in the
compilation |
| 4323 // units that were used to produce the constructorDeclarationMap. In such
cases, the |
| 4324 // constructor should already have its initializer AST's stored in it, but
we don't bother |
| 4325 // to check because there's nothing we can do about it at this point. |
| 4326 if (constructorDeclaration != null) { |
| 4327 _referenceGraph.addEdge(_source, constructorDeclaration); |
| 4328 } |
| 4329 } |
| 4330 return null; |
| 4331 } |
| 4332 } |
| 4333 |
| 4334 /** |
| 4335 * Instances of the class `StringState` represent the state of an object represe
nting a |
| 4336 * string. |
| 4337 */ |
| 4338 class StringState extends InstanceState { |
| 4339 /** |
| 4340 * The value of this instance. |
| 4341 */ |
| 4342 final String value; |
| 4343 |
| 4344 /** |
| 4345 * A state that can be used to represent a double whose value is not known. |
| 4346 */ |
| 4347 static StringState UNKNOWN_VALUE = new StringState(null); |
| 4348 |
| 4349 /** |
| 4350 * Initialize a newly created state to represent the given value. |
| 4351 * |
| 4352 * @param value the value of this instance |
| 4353 */ |
| 4354 StringState(this.value); |
| 4355 |
| 4356 @override |
| 4357 StringState concatenate(InstanceState rightOperand) { |
| 4358 if (value == null) { |
| 4359 return UNKNOWN_VALUE; |
| 4360 } |
| 4361 if (rightOperand is StringState) { |
| 4362 String rightValue = rightOperand.value; |
| 4363 if (rightValue == null) { |
| 4364 return UNKNOWN_VALUE; |
| 4365 } |
| 4366 return new StringState("${value}${rightValue}"); |
| 4367 } else if (rightOperand is DynamicState) { |
| 4368 return UNKNOWN_VALUE; |
| 4369 } |
| 4370 return super.concatenate(rightOperand); |
| 4371 } |
| 4372 |
| 4373 @override |
| 4374 StringState convertToString() => this; |
| 4375 |
| 4376 @override |
| 4377 BoolState equalEqual(InstanceState rightOperand) { |
| 4378 assertBoolNumStringOrNull(rightOperand); |
| 4379 if (value == null) { |
| 4380 return BoolState.UNKNOWN_VALUE; |
| 4381 } |
| 4382 if (rightOperand is StringState) { |
| 4383 String rightValue = rightOperand.value; |
| 4384 if (rightValue == null) { |
| 4385 return BoolState.UNKNOWN_VALUE; |
| 4386 } |
| 4387 return BoolState.from(value == rightValue); |
| 4388 } else if (rightOperand is DynamicState) { |
| 4389 return BoolState.UNKNOWN_VALUE; |
| 4390 } |
| 4391 return BoolState.FALSE_STATE; |
| 4392 } |
| 4393 |
| 4394 @override |
| 4395 bool operator ==(Object object) => object is StringState && (value == object.v
alue); |
| 4396 |
| 4397 @override |
| 4398 String get typeName => "String"; |
| 4399 |
| 4400 @override |
| 4401 bool get hasExactValue => true; |
| 4402 |
| 4403 @override |
| 4404 int get hashCode => value == null ? 0 : value.hashCode; |
| 4405 |
| 4406 @override |
| 4407 bool get isBoolNumStringOrNull => true; |
| 4408 |
| 4409 @override |
| 4410 bool get isUnknown => value == null; |
| 4411 |
| 4412 @override |
| 4413 String toString() => value == null ? "-unknown-" : "'${value}'"; |
| 4414 } |
| 4415 |
| 4416 /** |
| 4417 * Instances of the class `StringState` represent the state of an object represe
nting a |
| 4418 * symbol. |
| 4419 */ |
| 4420 class SymbolState extends InstanceState { |
| 4421 /** |
| 4422 * The value of this instance. |
| 4423 */ |
| 4424 final String value; |
| 4425 |
| 4426 /** |
| 4427 * Initialize a newly created state to represent the given value. |
| 4428 * |
| 4429 * @param value the value of this instance |
| 4430 */ |
| 4431 SymbolState(this.value); |
| 4432 |
| 4433 @override |
| 4434 StringState convertToString() { |
| 4435 if (value == null) { |
| 4436 return StringState.UNKNOWN_VALUE; |
| 4437 } |
| 4438 return new StringState(value); |
| 4439 } |
| 4440 |
| 4441 @override |
| 4442 BoolState equalEqual(InstanceState rightOperand) { |
| 4443 assertBoolNumStringOrNull(rightOperand); |
| 4444 if (value == null) { |
| 4445 return BoolState.UNKNOWN_VALUE; |
| 4446 } |
| 4447 if (rightOperand is SymbolState) { |
| 4448 String rightValue = rightOperand.value; |
| 4449 if (rightValue == null) { |
| 4450 return BoolState.UNKNOWN_VALUE; |
| 4451 } |
| 4452 return BoolState.from(value == rightValue); |
| 4453 } else if (rightOperand is DynamicState) { |
| 4454 return BoolState.UNKNOWN_VALUE; |
| 4455 } |
| 4456 return BoolState.FALSE_STATE; |
| 4457 } |
| 4458 |
| 4459 @override |
| 4460 bool operator ==(Object object) => object is SymbolState && (value == object.v
alue); |
| 4461 |
| 4462 @override |
| 4463 String get typeName => "Symbol"; |
| 4464 |
| 4465 @override |
| 4466 bool get hasExactValue => true; |
| 4467 |
| 4468 @override |
| 4469 int get hashCode => value == null ? 0 : value.hashCode; |
| 4470 |
| 4471 @override |
| 4472 String toString() => value == null ? "-unknown-" : "#${value}"; |
| 4473 } |
| 4474 |
| 4475 /** |
| 4476 * Instances of the class `TypeState` represent the state of an object represent
ing a type. |
| 4477 */ |
| 4478 class TypeState extends InstanceState { |
| 4479 /** |
| 4480 * The element representing the type being modeled. |
| 4481 */ |
| 4482 final Element _element; |
| 4483 |
| 4484 /** |
| 4485 * Initialize a newly created state to represent the given value. |
| 4486 * |
| 4487 * @param element the element representing the type being modeled |
| 4488 */ |
| 4489 TypeState(this._element); |
| 4490 |
| 4491 @override |
| 4492 StringState convertToString() { |
| 4493 if (_element == null) { |
| 4494 return StringState.UNKNOWN_VALUE; |
| 4495 } |
| 4496 return new StringState(_element.name); |
| 4497 } |
| 4498 |
| 4499 @override |
| 4500 bool operator ==(Object object) => object is TypeState && (_element == object.
_element); |
| 4501 |
| 4502 @override |
| 4503 BoolState equalEqual(InstanceState rightOperand) { |
| 4504 assertBoolNumStringOrNull(rightOperand); |
| 4505 if (_element == null) { |
| 4506 return BoolState.UNKNOWN_VALUE; |
| 4507 } |
| 4508 if (rightOperand is TypeState) { |
| 4509 Element rightElement = rightOperand._element; |
| 4510 if (rightElement == null) { |
| 4511 return BoolState.UNKNOWN_VALUE; |
| 4512 } |
| 4513 return BoolState.from(_element == rightElement); |
| 4514 } else if (rightOperand is DynamicState) { |
| 4515 return BoolState.UNKNOWN_VALUE; |
| 4516 } |
| 4517 return BoolState.FALSE_STATE; |
| 4518 } |
| 4519 |
| 4520 @override |
| 4521 String get typeName => "Type"; |
| 4522 |
| 4523 @override |
| 4524 int get hashCode => _element == null ? 0 : _element.hashCode; |
| 4525 |
| 4526 @override |
| 4527 String toString() => _element == null ? "-unknown-" : _element.name; |
| 4528 } |
| 4529 |
| 4530 /** |
| 4531 * Instances of the class `ValidResult` represent the result of attempting to ev
aluate a valid |
| 4532 * compile time constant expression. |
| 4533 */ |
| 4534 class ValidResult extends EvaluationResultImpl { |
| 4535 /** |
| 4536 * The value of the expression. |
| 4537 */ |
| 4538 final DartObjectImpl value; |
| 4539 |
| 4540 /** |
| 4541 * Initialize a newly created result to represent the given value. |
| 4542 * |
| 4543 * @param value the value of the expression |
| 4544 */ |
| 4545 ValidResult(this.value); |
| 4546 |
| 4547 @override |
| 4548 EvaluationResultImpl add(TypeProvider typeProvider, BinaryExpression node, Eva
luationResultImpl rightOperand) => rightOperand.addToValid(typeProvider, node, t
his); |
| 4549 |
| 4550 /** |
| 4551 * Return the result of applying boolean conversion to this result. |
| 4552 * |
| 4553 * @param node the node against which errors should be reported |
| 4554 * @return the result of applying boolean conversion to the given value |
| 4555 */ |
| 4556 @override |
| 4557 EvaluationResultImpl applyBooleanConversion(TypeProvider typeProvider, AstNode
node) { |
| 4558 try { |
| 4559 return _valueOf(value.convertToBool(typeProvider)); |
| 4560 } on EvaluationException catch (exception) { |
| 4561 return _error(node, exception.errorCode); |
| 4562 } |
| 4563 } |
| 4564 |
| 4565 @override |
| 4566 EvaluationResultImpl bitAnd(TypeProvider typeProvider, BinaryExpression node,
EvaluationResultImpl rightOperand) => rightOperand.bitAndValid(typeProvider, nod
e, this); |
| 4567 |
| 4568 @override |
| 4569 EvaluationResultImpl bitNot(TypeProvider typeProvider, Expression node) { |
| 4570 try { |
| 4571 return _valueOf(value.bitNot(typeProvider)); |
| 4572 } on EvaluationException catch (exception) { |
| 4573 return _error(node, exception.errorCode); |
| 4574 } |
| 4575 } |
| 4576 |
| 4577 @override |
| 4578 EvaluationResultImpl bitOr(TypeProvider typeProvider, BinaryExpression node, E
valuationResultImpl rightOperand) => rightOperand.bitOrValid(typeProvider, node,
this); |
| 4579 |
| 4580 @override |
| 4581 EvaluationResultImpl bitXor(TypeProvider typeProvider, BinaryExpression node,
EvaluationResultImpl rightOperand) => rightOperand.bitXorValid(typeProvider, nod
e, this); |
| 4582 |
| 4583 @override |
| 4584 EvaluationResultImpl concatenate(TypeProvider typeProvider, Expression node, E
valuationResultImpl rightOperand) => rightOperand.concatenateValid(typeProvider,
node, this); |
| 4585 |
| 4586 @override |
| 4587 EvaluationResultImpl divide(TypeProvider typeProvider, BinaryExpression node,
EvaluationResultImpl rightOperand) => rightOperand.divideValid(typeProvider, nod
e, this); |
| 4588 |
| 4589 @override |
| 4590 EvaluationResultImpl equalEqual(TypeProvider typeProvider, Expression node, Ev
aluationResultImpl rightOperand) => rightOperand.equalEqualValid(typeProvider, n
ode, this); |
| 4591 |
| 4592 @override |
| 4593 bool equalValues(TypeProvider typeProvider, EvaluationResultImpl result) { |
| 4594 if (result is! ValidResult) { |
| 4595 return false; |
| 4596 } |
| 4597 return value == (result as ValidResult).value; |
| 4598 } |
| 4599 |
| 4600 @override |
| 4601 EvaluationResultImpl greaterThan(TypeProvider typeProvider, BinaryExpression n
ode, EvaluationResultImpl rightOperand) => rightOperand.greaterThanValid(typePro
vider, node, this); |
| 4602 |
| 4603 @override |
| 4604 EvaluationResultImpl greaterThanOrEqual(TypeProvider typeProvider, BinaryExpre
ssion node, EvaluationResultImpl rightOperand) => rightOperand.greaterThanOrEqua
lValid(typeProvider, node, this); |
| 4605 |
| 4606 @override |
| 4607 EvaluationResultImpl integerDivide(TypeProvider typeProvider, BinaryExpression
node, EvaluationResultImpl rightOperand) => rightOperand.integerDivideValid(typ
eProvider, node, this); |
| 4608 |
| 4609 /** |
| 4610 * Return `true` if this object represents an object whose type is 'bool'. |
| 4611 * |
| 4612 * @return `true` if this object represents a boolean value |
| 4613 */ |
| 4614 bool get isBool => value.isBool; |
| 4615 |
| 4616 /** |
| 4617 * Return `true` if this object represents an object whose type is either 'boo
l', 'num', |
| 4618 * 'String', or 'Null'. |
| 4619 * |
| 4620 * @return `true` if this object represents either a boolean, numeric, string
or null value |
| 4621 */ |
| 4622 bool get isBoolNumStringOrNull => value.isBoolNumStringOrNull; |
| 4623 |
| 4624 /** |
| 4625 * Return `true` if this result represents the value 'false'. |
| 4626 * |
| 4627 * @return `true` if this result represents the value 'false' |
| 4628 */ |
| 4629 bool get isFalse => value.isFalse; |
| 4630 |
| 4631 /** |
| 4632 * Return `true` if this result represents the value 'null'. |
| 4633 * |
| 4634 * @return `true` if this result represents the value 'null' |
| 4635 */ |
| 4636 bool get isNull => value.isNull; |
| 4637 |
| 4638 /** |
| 4639 * Return `true` if this result represents the value 'true'. |
| 4640 * |
| 4641 * @return `true` if this result represents the value 'true' |
| 4642 */ |
| 4643 bool get isTrue => value.isTrue; |
| 4644 |
| 4645 /** |
| 4646 * Return `true` if this object represents an instance of a user-defined class
. |
| 4647 * |
| 4648 * @return `true` if this object represents an instance of a user-defined clas
s |
| 4649 */ |
| 4650 bool get isUserDefinedObject => value.isUserDefinedObject; |
| 4651 |
| 4652 @override |
| 4653 EvaluationResultImpl lessThan(TypeProvider typeProvider, BinaryExpression node
, EvaluationResultImpl rightOperand) => rightOperand.lessThanValid(typeProvider,
node, this); |
| 4654 |
| 4655 @override |
| 4656 EvaluationResultImpl lessThanOrEqual(TypeProvider typeProvider, BinaryExpressi
on node, EvaluationResultImpl rightOperand) => rightOperand.lessThanOrEqualValid
(typeProvider, node, this); |
| 4657 |
| 4658 @override |
| 4659 EvaluationResultImpl logicalAnd(TypeProvider typeProvider, BinaryExpression no
de, EvaluationResultImpl rightOperand) => rightOperand.logicalAndValid(typeProvi
der, node, this); |
| 4660 |
| 4661 @override |
| 4662 EvaluationResultImpl logicalNot(TypeProvider typeProvider, Expression node) { |
| 4663 try { |
| 4664 return _valueOf(value.logicalNot(typeProvider)); |
| 4665 } on EvaluationException catch (exception) { |
| 4666 return _error(node, exception.errorCode); |
| 4667 } |
| 4668 } |
| 4669 |
| 4670 @override |
| 4671 EvaluationResultImpl logicalOr(TypeProvider typeProvider, BinaryExpression nod
e, EvaluationResultImpl rightOperand) => rightOperand.logicalOrValid(typeProvide
r, node, this); |
| 4672 |
| 4673 @override |
| 4674 EvaluationResultImpl minus(TypeProvider typeProvider, BinaryExpression node, E
valuationResultImpl rightOperand) => rightOperand.minusValid(typeProvider, node,
this); |
| 4675 |
| 4676 @override |
| 4677 EvaluationResultImpl negated(TypeProvider typeProvider, Expression node) { |
| 4678 try { |
| 4679 return _valueOf(value.negated(typeProvider)); |
| 4680 } on EvaluationException catch (exception) { |
| 4681 return _error(node, exception.errorCode); |
| 4682 } |
| 4683 } |
| 4684 |
| 4685 @override |
| 4686 EvaluationResultImpl notEqual(TypeProvider typeProvider, BinaryExpression node
, EvaluationResultImpl rightOperand) => rightOperand.notEqualValid(typeProvider,
node, this); |
| 4687 |
| 4688 @override |
| 4689 EvaluationResultImpl performToString(TypeProvider typeProvider, AstNode node)
{ |
| 4690 try { |
| 4691 return _valueOf(value.performToString(typeProvider)); |
| 4692 } on EvaluationException catch (exception) { |
| 4693 return _error(node, exception.errorCode); |
| 4694 } |
| 4695 } |
| 4696 |
| 4697 @override |
| 4698 EvaluationResultImpl remainder(TypeProvider typeProvider, BinaryExpression nod
e, EvaluationResultImpl rightOperand) => rightOperand.remainderValid(typeProvide
r, node, this); |
| 4699 |
| 4700 @override |
| 4701 EvaluationResultImpl shiftLeft(TypeProvider typeProvider, BinaryExpression nod
e, EvaluationResultImpl rightOperand) => rightOperand.shiftLeftValid(typeProvide
r, node, this); |
| 4702 |
| 4703 @override |
| 4704 EvaluationResultImpl shiftRight(TypeProvider typeProvider, BinaryExpression no
de, EvaluationResultImpl rightOperand) => rightOperand.shiftRightValid(typeProvi
der, node, this); |
| 4705 |
| 4706 @override |
| 4707 EvaluationResultImpl times(TypeProvider typeProvider, BinaryExpression node, E
valuationResultImpl rightOperand) => rightOperand.timesValid(typeProvider, node,
this); |
| 4708 |
| 4709 @override |
| 4710 String toString() { |
| 4711 if (value == null) { |
| 4712 return "null"; |
| 4713 } |
| 4714 return value.toString(); |
| 4715 } |
| 4716 |
| 4717 @override |
| 4718 EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand
) => leftOperand; |
| 4719 |
| 4720 @override |
| 4721 EvaluationResultImpl addToValid(TypeProvider typeProvider, BinaryExpression no
de, ValidResult leftOperand) { |
| 4722 try { |
| 4723 return _valueOf(leftOperand.value.add(typeProvider, value)); |
| 4724 } on EvaluationException catch (exception) { |
| 4725 return _error(node, exception.errorCode); |
| 4726 } |
| 4727 } |
| 4728 |
| 4729 @override |
| 4730 EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperan
d) => leftOperand; |
| 4731 |
| 4732 @override |
| 4733 EvaluationResultImpl bitAndValid(TypeProvider typeProvider, BinaryExpression n
ode, ValidResult leftOperand) { |
| 4734 try { |
| 4735 return _valueOf(leftOperand.value.bitAnd(typeProvider, value)); |
| 4736 } on EvaluationException catch (exception) { |
| 4737 return _error(node, exception.errorCode); |
| 4738 } |
| 4739 } |
| 4740 |
| 4741 @override |
| 4742 EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand
) => leftOperand; |
| 4743 |
| 4744 @override |
| 4745 EvaluationResultImpl bitOrValid(TypeProvider typeProvider, BinaryExpression no
de, ValidResult leftOperand) { |
| 4746 try { |
| 4747 return _valueOf(leftOperand.value.bitOr(typeProvider, value)); |
| 4748 } on EvaluationException catch (exception) { |
| 4749 return _error(node, exception.errorCode); |
| 4750 } |
| 4751 } |
| 4752 |
| 4753 @override |
| 4754 EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperan
d) => leftOperand; |
| 4755 |
| 4756 @override |
| 4757 EvaluationResultImpl bitXorValid(TypeProvider typeProvider, BinaryExpression n
ode, ValidResult leftOperand) { |
| 4758 try { |
| 4759 return _valueOf(leftOperand.value.bitXor(typeProvider, value)); |
| 4760 } on EvaluationException catch (exception) { |
| 4761 return _error(node, exception.errorCode); |
| 4762 } |
| 4763 } |
| 4764 |
| 4765 @override |
| 4766 EvaluationResultImpl concatenateError(Expression node, ErrorResult leftOperand
) => leftOperand; |
| 4767 |
| 4768 @override |
| 4769 EvaluationResultImpl concatenateValid(TypeProvider typeProvider, Expression no
de, ValidResult leftOperand) { |
| 4770 try { |
| 4771 return _valueOf(leftOperand.value.concatenate(typeProvider, value)); |
| 4772 } on EvaluationException catch (exception) { |
| 4773 return _error(node, exception.errorCode); |
| 4774 } |
| 4775 } |
| 4776 |
| 4777 @override |
| 4778 EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperan
d) => leftOperand; |
| 4779 |
| 4780 @override |
| 4781 EvaluationResultImpl divideValid(TypeProvider typeProvider, BinaryExpression n
ode, ValidResult leftOperand) { |
| 4782 try { |
| 4783 return _valueOf(leftOperand.value.divide(typeProvider, value)); |
| 4784 } on EvaluationException catch (exception) { |
| 4785 return _error(node, exception.errorCode); |
| 4786 } |
| 4787 } |
| 4788 |
| 4789 @override |
| 4790 EvaluationResultImpl equalEqualError(Expression node, ErrorResult leftOperand)
=> leftOperand; |
| 4791 |
| 4792 @override |
| 4793 EvaluationResultImpl equalEqualValid(TypeProvider typeProvider, Expression nod
e, ValidResult leftOperand) { |
| 4794 try { |
| 4795 return _valueOf(leftOperand.value.equalEqual(typeProvider, value)); |
| 4796 } on EvaluationException catch (exception) { |
| 4797 return _error(node, exception.errorCode); |
| 4798 } |
| 4799 } |
| 4800 |
| 4801 @override |
| 4802 EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftO
perand) => leftOperand; |
| 4803 |
| 4804 @override |
| 4805 EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResul
t leftOperand) => leftOperand; |
| 4806 |
| 4807 @override |
| 4808 EvaluationResultImpl greaterThanOrEqualValid(TypeProvider typeProvider, Binary
Expression node, ValidResult leftOperand) { |
| 4809 try { |
| 4810 return _valueOf(leftOperand.value.greaterThanOrEqual(typeProvider, value))
; |
| 4811 } on EvaluationException catch (exception) { |
| 4812 return _error(node, exception.errorCode); |
| 4813 } |
| 4814 } |
| 4815 |
| 4816 @override |
| 4817 EvaluationResultImpl greaterThanValid(TypeProvider typeProvider, BinaryExpress
ion node, ValidResult leftOperand) { |
| 4818 try { |
| 4819 return _valueOf(leftOperand.value.greaterThan(typeProvider, value)); |
| 4820 } on EvaluationException catch (exception) { |
| 4821 return _error(node, exception.errorCode); |
| 4822 } |
| 4823 } |
| 4824 |
| 4825 @override |
| 4826 EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult lef
tOperand) => leftOperand; |
| 4827 |
| 4828 @override |
| 4829 EvaluationResultImpl integerDivideValid(TypeProvider typeProvider, BinaryExpre
ssion node, ValidResult leftOperand) { |
| 4830 try { |
| 4831 return _valueOf(leftOperand.value.integerDivide(typeProvider, value)); |
| 4832 } on EvaluationException catch (exception) { |
| 4833 return _error(node, exception.errorCode); |
| 4834 } |
| 4835 } |
| 4836 |
| 4837 @override |
| 4838 EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOper
and) => leftOperand; |
| 4839 |
| 4840 @override |
| 4841 EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult l
eftOperand) => leftOperand; |
| 4842 |
| 4843 @override |
| 4844 EvaluationResultImpl lessThanOrEqualValid(TypeProvider typeProvider, BinaryExp
ression node, ValidResult leftOperand) { |
| 4845 try { |
| 4846 return _valueOf(leftOperand.value.lessThanOrEqual(typeProvider, value)); |
| 4847 } on EvaluationException catch (exception) { |
| 4848 return _error(node, exception.errorCode); |
| 4849 } |
| 4850 } |
| 4851 |
| 4852 @override |
| 4853 EvaluationResultImpl lessThanValid(TypeProvider typeProvider, BinaryExpression
node, ValidResult leftOperand) { |
| 4854 try { |
| 4855 return _valueOf(leftOperand.value.lessThan(typeProvider, value)); |
| 4856 } on EvaluationException catch (exception) { |
| 4857 return _error(node, exception.errorCode); |
| 4858 } |
| 4859 } |
| 4860 |
| 4861 @override |
| 4862 EvaluationResultImpl logicalAndError(BinaryExpression node, ErrorResult leftOp
erand) => leftOperand; |
| 4863 |
| 4864 @override |
| 4865 EvaluationResultImpl logicalAndValid(TypeProvider typeProvider, BinaryExpressi
on node, ValidResult leftOperand) { |
| 4866 try { |
| 4867 return _valueOf(leftOperand.value.logicalAnd(typeProvider, value)); |
| 4868 } on EvaluationException catch (exception) { |
| 4869 return _error(node, exception.errorCode); |
| 4870 } |
| 4871 } |
| 4872 |
| 4873 @override |
| 4874 EvaluationResultImpl logicalOrError(BinaryExpression node, ErrorResult leftOpe
rand) => leftOperand; |
| 4875 |
| 4876 @override |
| 4877 EvaluationResultImpl logicalOrValid(TypeProvider typeProvider, BinaryExpressio
n node, ValidResult leftOperand) { |
| 4878 try { |
| 4879 return _valueOf(leftOperand.value.logicalOr(typeProvider, value)); |
| 4880 } on EvaluationException catch (exception) { |
| 4881 return _error(node, exception.errorCode); |
| 4882 } |
| 4883 } |
| 4884 |
| 4885 @override |
| 4886 EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand
) => leftOperand; |
| 4887 |
| 4888 @override |
| 4889 EvaluationResultImpl minusValid(TypeProvider typeProvider, BinaryExpression no
de, ValidResult leftOperand) { |
| 4890 try { |
| 4891 return _valueOf(leftOperand.value.minus(typeProvider, value)); |
| 4892 } on EvaluationException catch (exception) { |
| 4893 return _error(node, exception.errorCode); |
| 4894 } |
| 4895 } |
| 4896 |
| 4897 @override |
| 4898 EvaluationResultImpl notEqualError(BinaryExpression node, ErrorResult leftOper
and) => leftOperand; |
| 4899 |
| 4900 @override |
| 4901 EvaluationResultImpl notEqualValid(TypeProvider typeProvider, BinaryExpression
node, ValidResult leftOperand) { |
| 4902 try { |
| 4903 return _valueOf(leftOperand.value.notEqual(typeProvider, value)); |
| 4904 } on EvaluationException catch (exception) { |
| 4905 return _error(node, exception.errorCode); |
| 4906 } |
| 4907 } |
| 4908 |
| 4909 @override |
| 4910 EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOpe
rand) => leftOperand; |
| 4911 |
| 4912 @override |
| 4913 EvaluationResultImpl remainderValid(TypeProvider typeProvider, BinaryExpressio
n node, ValidResult leftOperand) { |
| 4914 try { |
| 4915 return _valueOf(leftOperand.value.remainder(typeProvider, value)); |
| 4916 } on EvaluationException catch (exception) { |
| 4917 return _error(node, exception.errorCode); |
| 4918 } |
| 4919 } |
| 4920 |
| 4921 @override |
| 4922 EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOpe
rand) => leftOperand; |
| 4923 |
| 4924 @override |
| 4925 EvaluationResultImpl shiftLeftValid(TypeProvider typeProvider, BinaryExpressio
n node, ValidResult leftOperand) { |
| 4926 try { |
| 4927 return _valueOf(leftOperand.value.shiftLeft(typeProvider, value)); |
| 4928 } on EvaluationException catch (exception) { |
| 4929 return _error(node, exception.errorCode); |
| 4930 } |
| 4931 } |
| 4932 |
| 4933 @override |
| 4934 EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOp
erand) => leftOperand; |
| 4935 |
| 4936 @override |
| 4937 EvaluationResultImpl shiftRightValid(TypeProvider typeProvider, BinaryExpressi
on node, ValidResult leftOperand) { |
| 4938 try { |
| 4939 return _valueOf(leftOperand.value.shiftRight(typeProvider, value)); |
| 4940 } on EvaluationException catch (exception) { |
| 4941 return _error(node, exception.errorCode); |
| 4942 } |
| 4943 } |
| 4944 |
| 4945 @override |
| 4946 EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand
) => leftOperand; |
| 4947 |
| 4948 @override |
| 4949 EvaluationResultImpl timesValid(TypeProvider typeProvider, BinaryExpression no
de, ValidResult leftOperand) { |
| 4950 try { |
| 4951 return _valueOf(leftOperand.value.times(typeProvider, value)); |
| 4952 } on EvaluationException catch (exception) { |
| 4953 return _error(node, exception.errorCode); |
| 4954 } |
| 4955 } |
| 4956 |
| 4957 /** |
| 4958 * Return a result object representing an error associated with the given node
. |
| 4959 * |
| 4960 * @param node the AST node associated with the error |
| 4961 * @param code the error code indicating the nature of the error |
| 4962 * @return a result object representing an error associated with the given nod
e |
| 4963 */ |
| 4964 ErrorResult _error(AstNode node, ErrorCode code) => new ErrorResult.con1(node,
code); |
| 4965 |
| 4966 /** |
| 4967 * Return a result object representing the given value. |
| 4968 * |
| 4969 * @param value the value to be represented as a result object |
| 4970 * @return a result object representing the given value |
| 4971 */ |
| 4972 ValidResult _valueOf(DartObjectImpl value) => new ValidResult(value); |
| 4973 } |
OLD | NEW |