| OLD | NEW |
| (Empty) |
| 1 // This code was auto-generated, is not intended to be edited, and is subject to | |
| 2 // significant change. Please see the README file for more information. | |
| 3 library engine.constant; | |
| 4 import 'java_core.dart'; | |
| 5 import 'source.dart' show Source; | |
| 6 import 'error.dart' show AnalysisError, ErrorCode, CompileTimeErrorCode; | |
| 7 import 'scanner.dart' show TokenType; | |
| 8 import 'ast.dart'; | |
| 9 import 'element.dart'; | |
| 10 import 'engine.dart' show AnalysisEngine; | |
| 11 /** | |
| 12 * Instances of the class `ConstantEvaluator` evaluate constant expressions to p
roduce their | |
| 13 * compile-time value. According to the Dart Language Specification: <blockquote
> A constant | |
| 14 * expression is one of the following: | |
| 15 * | |
| 16 * * A literal number. | |
| 17 * * A literal boolean. | |
| 18 * * A literal string where any interpolated expression is a compile-time consta
nt that evaluates | |
| 19 * to a numeric, string or boolean value or to `null`. | |
| 20 * * `null`. | |
| 21 * * A reference to a static constant variable. | |
| 22 * * An identifier expression that denotes a constant variable, a class or a typ
e parameter. | |
| 23 * * A constant constructor invocation. | |
| 24 * * A constant list literal. | |
| 25 * * A constant map literal. | |
| 26 * * A simple or qualified identifier denoting a top-level function or a static
method. | |
| 27 * * A parenthesized expression `(e)` where `e` is a constant expression. | |
| 28 * * An expression of one of the forms `identical(e1, e2)`, `e1 == e2`, | |
| 29 * `e1 != e2` where `e1` and `e2` are constant expressions that evaluate to a | |
| 30 * numeric, string or boolean value or to `null`. | |
| 31 * * An expression of one of the forms `!e`, `e1 && e2` or `e1 || e2`, where | |
| 32 * `e`, `e1` and `e2` are constant expressions that evaluate to a boolean value
or | |
| 33 * to `null`. | |
| 34 * * An expression of one of the forms `~e`, `e1 ^ e2`, `e1 & e2`, | |
| 35 * `e1 | e2`, `e1 >> e2` or `e1 << e2`, where `e`, `e1` and `e2` | |
| 36 * are constant expressions that evaluate to an integer value or to `null`. | |
| 37 * * An expression of one of the forms `-e`, `e1 + e2`, `e1 - e2`, | |
| 38 * `e1 * e2`, `e1 / e2`, `e1 ~/ e2`, `e1 > e2`, `e1 < e2`, | |
| 39 * `e1 >= e2`, `e1 <= e2` or `e1 % e2`, where `e`, `e1` and `e2` | |
| 40 * are constant expressions that evaluate to a numeric value or to `null`. | |
| 41 * | |
| 42 * </blockquote> The values returned by instances of this class are therefore `n
ull` and | |
| 43 * instances of the classes `Boolean`, `BigInteger`, `Double`, `String`, and | |
| 44 * `DartObject`. | |
| 45 * | |
| 46 * In addition, this class defines several values that can be returned to indica
te various | |
| 47 * conditions encountered during evaluation. These are documented with the stati
c field that define | |
| 48 * those values. | |
| 49 */ | |
| 50 class ConstantEvaluator { | |
| 51 | |
| 52 /** | |
| 53 * The source containing the expression(s) that will be evaluated. | |
| 54 */ | |
| 55 Source _source; | |
| 56 | |
| 57 /** | |
| 58 * Initialize a newly created evaluator to evaluate expressions in the given s
ource. | |
| 59 * | |
| 60 * @param source the source containing the expression(s) that will be evaluate
d | |
| 61 */ | |
| 62 ConstantEvaluator(Source source) { | |
| 63 this._source = source; | |
| 64 } | |
| 65 EvaluationResult evaluate(Expression expression) { | |
| 66 EvaluationResultImpl result = expression.accept(new ConstantVisitor()); | |
| 67 if (result is ValidResult) { | |
| 68 return EvaluationResult.forValue(((result as ValidResult)).value); | |
| 69 } | |
| 70 List<AnalysisError> errors = new List<AnalysisError>(); | |
| 71 for (ErrorResult_ErrorData data in ((result as ErrorResult)).errorData) { | |
| 72 ASTNode node = data.node; | |
| 73 errors.add(new AnalysisError.con2(_source, node.offset, node.length, data.
errorCode, [])); | |
| 74 } | |
| 75 return EvaluationResult.forErrors(new List.from(errors)); | |
| 76 } | |
| 77 } | |
| 78 /** | |
| 79 * Instances of the class `EvaluationResult` represent the result of attempting
to evaluate an | |
| 80 * expression. | |
| 81 */ | |
| 82 class EvaluationResult { | |
| 83 | |
| 84 /** | |
| 85 * Return an evaluation result representing the result of evaluating an expres
sion that is not a | |
| 86 * compile-time constant because of the given errors. | |
| 87 * | |
| 88 * @param errors the errors that should be reported for the expression(s) that
were evaluated | |
| 89 * @return the result of evaluating an expression that is not a compile-time c
onstant | |
| 90 */ | |
| 91 static EvaluationResult forErrors(List<AnalysisError> errors) => new Evaluatio
nResult(null, errors); | |
| 92 | |
| 93 /** | |
| 94 * Return an evaluation result representing the result of evaluating an expres
sion that is a | |
| 95 * compile-time constant that evaluates to the given value. | |
| 96 * | |
| 97 * @param value the value of the expression | |
| 98 * @return the result of evaluating an expression that is a compile-time const
ant | |
| 99 */ | |
| 100 static EvaluationResult forValue(Object value) => new EvaluationResult(value,
null); | |
| 101 | |
| 102 /** | |
| 103 * The value of the expression. | |
| 104 */ | |
| 105 Object value; | |
| 106 | |
| 107 /** | |
| 108 * The errors that should be reported for the expression(s) that were evaluate
d. | |
| 109 */ | |
| 110 List<AnalysisError> _errors; | |
| 111 | |
| 112 /** | |
| 113 * Initialize a newly created result object with the given state. Clients shou
ld use one of the | |
| 114 * factory methods: [forErrors] and [forValue]. | |
| 115 * | |
| 116 * @param value the value of the expression | |
| 117 * @param errors the errors that should be reported for the expression(s) that
were evaluated | |
| 118 */ | |
| 119 EvaluationResult(Object value, List<AnalysisError> errors) { | |
| 120 this.value = value; | |
| 121 this._errors = errors; | |
| 122 } | |
| 123 | |
| 124 /** | |
| 125 * Return an array containing the errors that should be reported for the expre
ssion(s) that were | |
| 126 * evaluated. If there are no such errors, the array will be empty. The array
can be empty even if | |
| 127 * the expression is not a valid compile time constant if the errors would hav
e been reported by | |
| 128 * other parts of the analysis engine. | |
| 129 */ | |
| 130 List<AnalysisError> get errors => _errors == null ? AnalysisError.NO_ERRORS :
_errors; | |
| 131 | |
| 132 /** | |
| 133 * Return `true` if the expression is a compile-time constant expression that
would not | |
| 134 * throw an exception when evaluated. | |
| 135 * | |
| 136 * @return `true` if the expression is a valid compile-time constant expressio
n | |
| 137 */ | |
| 138 bool get isValid => _errors == null; | |
| 139 } | |
| 140 /** | |
| 141 * Instances of the class `ConstantFinder` are used to traverse the AST structur
es of all of | |
| 142 * the compilation units being resolved and build a table mapping constant varia
ble elements to the | |
| 143 * declarations of those variables. | |
| 144 */ | |
| 145 class ConstantFinder extends RecursiveASTVisitor<Object> { | |
| 146 | |
| 147 /** | |
| 148 * A table mapping constant variable elements to the declarations of those var
iables. | |
| 149 */ | |
| 150 final Map<VariableElement, VariableDeclaration> variableMap = new Map<Variable
Element, VariableDeclaration>(); | |
| 151 Object visitVariableDeclaration(VariableDeclaration node) { | |
| 152 super.visitVariableDeclaration(node); | |
| 153 Expression initializer = node.initializer; | |
| 154 if (initializer != null && node.isConst) { | |
| 155 VariableElement element = node.element; | |
| 156 if (element != null) { | |
| 157 variableMap[element] = node; | |
| 158 } | |
| 159 } | |
| 160 return null; | |
| 161 } | |
| 162 } | |
| 163 /** | |
| 164 * Instances of the class `ConstantValueComputer` compute the values of constant
variables in | |
| 165 * one or more compilation units. The expected usage pattern is for the compilat
ion units to be | |
| 166 * added to this computer using the method [add] and then for the method | |
| 167 * [computeValues] to invoked exactly once. Any use of an instance after invokin
g the | |
| 168 * method [computeValues] will result in unpredictable behavior. | |
| 169 */ | |
| 170 class ConstantValueComputer { | |
| 171 | |
| 172 /** | |
| 173 * The object used to find constant variables in the compilation units that we
re added. | |
| 174 */ | |
| 175 ConstantFinder _constantFinder = new ConstantFinder(); | |
| 176 | |
| 177 /** | |
| 178 * A graph in which the nodes are the constant variables and the edges are fro
m each variable to | |
| 179 * the other constant variables that are referenced in the head's initializer. | |
| 180 */ | |
| 181 DirectedGraph<VariableElement> _referenceGraph = new DirectedGraph<VariableEle
ment>(); | |
| 182 | |
| 183 /** | |
| 184 * A table mapping constant variables to the declarations of those variables. | |
| 185 */ | |
| 186 Map<VariableElement, VariableDeclaration> _declarationMap; | |
| 187 | |
| 188 /** | |
| 189 * Add the constant variables in the given compilation unit to the list of con
stant variables | |
| 190 * whose value needs to be computed. | |
| 191 * | |
| 192 * @param unit the compilation unit defining the constant variables to be adde
d | |
| 193 */ | |
| 194 void add(CompilationUnit unit) { | |
| 195 unit.accept(_constantFinder); | |
| 196 } | |
| 197 | |
| 198 /** | |
| 199 * Compute values for all of the constant variables in the compilation units t
hat were added. | |
| 200 */ | |
| 201 void computeValues() { | |
| 202 _declarationMap = _constantFinder.variableMap; | |
| 203 for (MapEntry<VariableElement, VariableDeclaration> entry in getMapEntrySet(
_declarationMap)) { | |
| 204 VariableElement element = entry.getKey(); | |
| 205 ReferenceFinder referenceFinder = new ReferenceFinder(element, _referenceG
raph); | |
| 206 _referenceGraph.addNode(element); | |
| 207 entry.getValue().initializer.accept(referenceFinder); | |
| 208 } | |
| 209 while (!_referenceGraph.isEmpty) { | |
| 210 VariableElement element = _referenceGraph.removeSink(); | |
| 211 while (element != null) { | |
| 212 computeValueFor(element); | |
| 213 element = _referenceGraph.removeSink(); | |
| 214 } | |
| 215 if (!_referenceGraph.isEmpty) { | |
| 216 List<VariableElement> variablesInCycle = _referenceGraph.findCycle(); | |
| 217 if (variablesInCycle == null) { | |
| 218 AnalysisEngine.instance.logger.logError("Exiting constant value comput
er with ${_referenceGraph.nodeCount} variables that are neither sinks no in a cy
cle"); | |
| 219 return; | |
| 220 } | |
| 221 for (VariableElement variable in variablesInCycle) { | |
| 222 generateCycleError(variablesInCycle, variable); | |
| 223 } | |
| 224 _referenceGraph.removeAllNodes(variablesInCycle); | |
| 225 } | |
| 226 } | |
| 227 } | |
| 228 | |
| 229 /** | |
| 230 * Compute a value for the given variable. | |
| 231 * | |
| 232 * @param variable the variable for which a value is to be computed | |
| 233 */ | |
| 234 void computeValueFor(VariableElement variable) { | |
| 235 VariableDeclaration declaration = _declarationMap[variable]; | |
| 236 if (declaration == null) { | |
| 237 return; | |
| 238 } | |
| 239 EvaluationResultImpl result = declaration.initializer.accept(new ConstantVis
itor()); | |
| 240 ((variable as VariableElementImpl)).evaluationResult = result; | |
| 241 if (result is ErrorResult) { | |
| 242 List<AnalysisError> errors = new List<AnalysisError>(); | |
| 243 for (ErrorResult_ErrorData data in ((result as ErrorResult)).errorData) { | |
| 244 ASTNode node = data.node; | |
| 245 Source source = variable.getAncestor(CompilationUnitElement).source; | |
| 246 errors.add(new AnalysisError.con2(source, node.offset, node.length, data
.errorCode, [])); | |
| 247 } | |
| 248 } | |
| 249 } | |
| 250 | |
| 251 /** | |
| 252 * Generate an error indicating that the given variable is not a valid compile
-time constant | |
| 253 * because it references at least one of the variables in the given cycle, eac
h of which directly | |
| 254 * or indirectly references the variable. | |
| 255 * | |
| 256 * @param variablesInCycle the variables in the cycle that includes the given
variable | |
| 257 * @param variable the variable that is not a valid compile-time constant | |
| 258 */ | |
| 259 void generateCycleError(List<VariableElement> variablesInCycle, VariableElemen
t variable) { | |
| 260 } | |
| 261 } | |
| 262 /** | |
| 263 * Instances of the class `ConstantVisitor` evaluate constant expressions to pro
duce their | |
| 264 * compile-time value. According to the Dart Language Specification: <blockquote
> A constant | |
| 265 * expression is one of the following: | |
| 266 * | |
| 267 * * A literal number. | |
| 268 * * A literal boolean. | |
| 269 * * A literal string where any interpolated expression is a compile-time consta
nt that evaluates | |
| 270 * to a numeric, string or boolean value or to `null`. | |
| 271 * * `null`. | |
| 272 * * A reference to a static constant variable. | |
| 273 * * An identifier expression that denotes a constant variable, a class or a typ
e parameter. | |
| 274 * * A constant constructor invocation. | |
| 275 * * A constant list literal. | |
| 276 * * A constant map literal. | |
| 277 * * A simple or qualified identifier denoting a top-level function or a static
method. | |
| 278 * * A parenthesized expression `(e)` where `e` is a constant expression. | |
| 279 * * An expression of one of the forms `identical(e1, e2)`, `e1 == e2`, | |
| 280 * `e1 != e2` where `e1` and `e2` are constant expressions that evaluate to a | |
| 281 * numeric, string or boolean value or to `null`. | |
| 282 * * An expression of one of the forms `!e`, `e1 && e2` or `e1 || e2`, where | |
| 283 * `e`, `e1` and `e2` are constant expressions that evaluate to a boolean value
or | |
| 284 * to `null`. | |
| 285 * * An expression of one of the forms `~e`, `e1 ^ e2`, `e1 & e2`, | |
| 286 * `e1 | e2`, `e1 >> e2` or `e1 << e2`, where `e`, `e1` and `e2` | |
| 287 * are constant expressions that evaluate to an integer value or to `null`. | |
| 288 * * An expression of one of the forms `-e`, `e1 + e2`, `e1 - e2`, | |
| 289 * `e1 * e2`, `e1 / e2`, `e1 ~/ e2`, `e1 > e2`, `e1 < e2`, | |
| 290 * `e1 >= e2`, `e1 <= e2` or `e1 % e2`, where `e`, `e1` and `e2` | |
| 291 * are constant expressions that evaluate to a numeric value or to `null`. | |
| 292 * | |
| 293 * </blockquote> | |
| 294 */ | |
| 295 class ConstantVisitor extends UnifyingASTVisitor<EvaluationResultImpl> { | |
| 296 EvaluationResultImpl visitAdjacentStrings(AdjacentStrings node) { | |
| 297 EvaluationResultImpl result = null; | |
| 298 for (StringLiteral string in node.strings) { | |
| 299 if (result == null) { | |
| 300 result = string.accept(this); | |
| 301 } else { | |
| 302 result = result.concatenate(node, string.accept(this)); | |
| 303 } | |
| 304 } | |
| 305 return result; | |
| 306 } | |
| 307 EvaluationResultImpl visitBinaryExpression(BinaryExpression node) { | |
| 308 EvaluationResultImpl leftResult = node.leftOperand.accept(this); | |
| 309 EvaluationResultImpl rightResult = node.rightOperand.accept(this); | |
| 310 TokenType operatorType = node.operator.type; | |
| 311 if (operatorType != TokenType.BANG_EQ && operatorType != TokenType.EQ_EQ) { | |
| 312 if (leftResult is ValidResult && ((leftResult as ValidResult)).isNull || r
ightResult is ValidResult && ((rightResult as ValidResult)).isNull) { | |
| 313 return error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION); | |
| 314 } | |
| 315 } | |
| 316 while (true) { | |
| 317 if (operatorType == TokenType.AMPERSAND) { | |
| 318 return leftResult.bitAnd(node, rightResult); | |
| 319 } else if (operatorType == TokenType.AMPERSAND_AMPERSAND) { | |
| 320 return leftResult.logicalAnd(node, rightResult); | |
| 321 } else if (operatorType == TokenType.BANG_EQ) { | |
| 322 return leftResult.notEqual(node, rightResult); | |
| 323 } else if (operatorType == TokenType.BAR) { | |
| 324 return leftResult.bitOr(node, rightResult); | |
| 325 } else if (operatorType == TokenType.BAR_BAR) { | |
| 326 return leftResult.logicalOr(node, rightResult); | |
| 327 } else if (operatorType == TokenType.CARET) { | |
| 328 return leftResult.bitXor(node, rightResult); | |
| 329 } else if (operatorType == TokenType.EQ_EQ) { | |
| 330 return leftResult.equalEqual(node, rightResult); | |
| 331 } else if (operatorType == TokenType.GT) { | |
| 332 return leftResult.greaterThan(node, rightResult); | |
| 333 } else if (operatorType == TokenType.GT_EQ) { | |
| 334 return leftResult.greaterThanOrEqual(node, rightResult); | |
| 335 } else if (operatorType == TokenType.GT_GT) { | |
| 336 return leftResult.shiftRight(node, rightResult); | |
| 337 } else if (operatorType == TokenType.LT) { | |
| 338 return leftResult.lessThan(node, rightResult); | |
| 339 } else if (operatorType == TokenType.LT_EQ) { | |
| 340 return leftResult.lessThanOrEqual(node, rightResult); | |
| 341 } else if (operatorType == TokenType.LT_LT) { | |
| 342 return leftResult.shiftLeft(node, rightResult); | |
| 343 } else if (operatorType == TokenType.MINUS) { | |
| 344 return leftResult.minus(node, rightResult); | |
| 345 } else if (operatorType == TokenType.PERCENT) { | |
| 346 return leftResult.remainder(node, rightResult); | |
| 347 } else if (operatorType == TokenType.PLUS) { | |
| 348 return leftResult.add(node, rightResult); | |
| 349 } else if (operatorType == TokenType.STAR) { | |
| 350 return leftResult.times(node, rightResult); | |
| 351 } else if (operatorType == TokenType.SLASH) { | |
| 352 return leftResult.divide(node, rightResult); | |
| 353 } else if (operatorType == TokenType.TILDE_SLASH) { | |
| 354 return leftResult.integerDivide(node, rightResult); | |
| 355 } | |
| 356 break; | |
| 357 } | |
| 358 return error(node, null); | |
| 359 } | |
| 360 EvaluationResultImpl visitBooleanLiteral(BooleanLiteral node) => node.value ?
ValidResult.RESULT_TRUE : ValidResult.RESULT_FALSE; | |
| 361 EvaluationResultImpl visitConditionalExpression(ConditionalExpression node) { | |
| 362 Expression condition = node.condition; | |
| 363 EvaluationResultImpl conditionResult = condition.accept(this); | |
| 364 conditionResult = conditionResult.applyBooleanConversion(condition); | |
| 365 if (conditionResult is ErrorResult) { | |
| 366 return conditionResult; | |
| 367 } | |
| 368 EvaluationResultImpl thenResult = node.thenExpression.accept(this); | |
| 369 if (thenResult is ErrorResult) { | |
| 370 return thenResult; | |
| 371 } | |
| 372 EvaluationResultImpl elseResult = node.elseExpression.accept(this); | |
| 373 if (elseResult is ErrorResult) { | |
| 374 return elseResult; | |
| 375 } | |
| 376 return (identical(conditionResult, ValidResult.RESULT_TRUE)) ? thenResult :
elseResult; | |
| 377 } | |
| 378 EvaluationResultImpl visitDoubleLiteral(DoubleLiteral node) => new ValidResult
(node.value); | |
| 379 EvaluationResultImpl visitInstanceCreationExpression(InstanceCreationExpressio
n node) { | |
| 380 if (!node.isConst) { | |
| 381 return error(node, null); | |
| 382 } | |
| 383 ConstructorElement constructor = node.staticElement; | |
| 384 if (constructor != null && constructor.isConst) { | |
| 385 node.argumentList.accept(this); | |
| 386 return ValidResult.RESULT_OBJECT; | |
| 387 } | |
| 388 return error(node, null); | |
| 389 } | |
| 390 EvaluationResultImpl visitIntegerLiteral(IntegerLiteral node) => new ValidResu
lt(node.value); | |
| 391 EvaluationResultImpl visitInterpolationExpression(InterpolationExpression node
) { | |
| 392 EvaluationResultImpl result = node.expression.accept(this); | |
| 393 return result.performToString(node); | |
| 394 } | |
| 395 EvaluationResultImpl visitInterpolationString(InterpolationString node) => new
ValidResult(node.value); | |
| 396 EvaluationResultImpl visitListLiteral(ListLiteral node) { | |
| 397 if (node.constKeyword == null) { | |
| 398 return new ErrorResult.con1(node, CompileTimeErrorCode.MISSING_CONST_IN_LI
ST_LITERAL); | |
| 399 } | |
| 400 ErrorResult result = null; | |
| 401 for (Expression element in node.elements) { | |
| 402 result = union(result, element.accept(this)); | |
| 403 } | |
| 404 if (result != null) { | |
| 405 return result; | |
| 406 } | |
| 407 return ValidResult.RESULT_OBJECT; | |
| 408 } | |
| 409 EvaluationResultImpl visitMapLiteral(MapLiteral node) { | |
| 410 if (node.constKeyword == null) { | |
| 411 return new ErrorResult.con1(node, CompileTimeErrorCode.MISSING_CONST_IN_MA
P_LITERAL); | |
| 412 } | |
| 413 ErrorResult result = null; | |
| 414 for (MapLiteralEntry entry in node.entries) { | |
| 415 result = union(result, entry.key.accept(this)); | |
| 416 result = union(result, entry.value.accept(this)); | |
| 417 } | |
| 418 if (result != null) { | |
| 419 return result; | |
| 420 } | |
| 421 return ValidResult.RESULT_OBJECT; | |
| 422 } | |
| 423 EvaluationResultImpl visitMethodInvocation(MethodInvocation node) { | |
| 424 Element element = node.methodName.staticElement; | |
| 425 if (element is FunctionElement) { | |
| 426 FunctionElement function = element as FunctionElement; | |
| 427 if (function.name == "identical") { | |
| 428 NodeList<Expression> arguments = node.argumentList.arguments; | |
| 429 if (arguments.length == 2) { | |
| 430 Element enclosingElement = function.enclosingElement; | |
| 431 if (enclosingElement is CompilationUnitElement) { | |
| 432 LibraryElement library = ((enclosingElement as CompilationUnitElemen
t)).library; | |
| 433 if (library.isDartCore) { | |
| 434 EvaluationResultImpl leftArgument = arguments[0].accept(this); | |
| 435 EvaluationResultImpl rightArgument = arguments[1].accept(this); | |
| 436 return leftArgument.equalEqual(node, rightArgument); | |
| 437 } | |
| 438 } | |
| 439 } | |
| 440 } | |
| 441 } | |
| 442 return error(node, null); | |
| 443 } | |
| 444 EvaluationResultImpl visitNamedExpression(NamedExpression node) => node.expres
sion.accept(this); | |
| 445 EvaluationResultImpl visitNode(ASTNode node) => error(node, null); | |
| 446 EvaluationResultImpl visitNullLiteral(NullLiteral node) => ValidResult.RESULT_
NULL; | |
| 447 EvaluationResultImpl visitParenthesizedExpression(ParenthesizedExpression node
) => node.expression.accept(this); | |
| 448 EvaluationResultImpl visitPrefixedIdentifier(PrefixedIdentifier node) { | |
| 449 SimpleIdentifier prefixNode = node.prefix; | |
| 450 Element prefixElement = prefixNode.staticElement; | |
| 451 if (prefixElement is! PrefixElement) { | |
| 452 EvaluationResultImpl prefixResult = prefixNode.accept(this); | |
| 453 if (prefixResult is! ValidResult) { | |
| 454 return error(node, null); | |
| 455 } | |
| 456 } | |
| 457 return getConstantValue(node, node.staticElement); | |
| 458 } | |
| 459 EvaluationResultImpl visitPrefixExpression(PrefixExpression node) { | |
| 460 EvaluationResultImpl operand = node.operand.accept(this); | |
| 461 if (operand is ValidResult && ((operand as ValidResult)).isNull) { | |
| 462 return error(node, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION); | |
| 463 } | |
| 464 while (true) { | |
| 465 if (node.operator.type == TokenType.BANG) { | |
| 466 return operand.logicalNot(node); | |
| 467 } else if (node.operator.type == TokenType.TILDE) { | |
| 468 return operand.bitNot(node); | |
| 469 } else if (node.operator.type == TokenType.MINUS) { | |
| 470 return operand.negated(node); | |
| 471 } | |
| 472 break; | |
| 473 } | |
| 474 return error(node, null); | |
| 475 } | |
| 476 EvaluationResultImpl visitPropertyAccess(PropertyAccess node) => getConstantVa
lue(node, node.propertyName.staticElement); | |
| 477 EvaluationResultImpl visitSimpleIdentifier(SimpleIdentifier node) => getConsta
ntValue(node, node.staticElement); | |
| 478 EvaluationResultImpl visitSimpleStringLiteral(SimpleStringLiteral node) => new
ValidResult(node.value); | |
| 479 EvaluationResultImpl visitStringInterpolation(StringInterpolation node) { | |
| 480 EvaluationResultImpl result = null; | |
| 481 for (InterpolationElement element in node.elements) { | |
| 482 if (result == null) { | |
| 483 result = element.accept(this); | |
| 484 } else { | |
| 485 result = result.concatenate(node, element.accept(this)); | |
| 486 } | |
| 487 } | |
| 488 return result; | |
| 489 } | |
| 490 EvaluationResultImpl visitSymbolLiteral(SymbolLiteral node) => ValidResult.RES
ULT_SYMBOL; | |
| 491 | |
| 492 /** | |
| 493 * Return a result object representing an error associated with the given node
. | |
| 494 * | |
| 495 * @param node the AST node associated with the error | |
| 496 * @param code the error code indicating the nature of the error | |
| 497 * @return a result object representing an error associated with the given nod
e | |
| 498 */ | |
| 499 ErrorResult error(ASTNode node, ErrorCode code) => new ErrorResult.con1(node,
code == null ? CompileTimeErrorCode.INVALID_CONSTANT : code); | |
| 500 | |
| 501 /** | |
| 502 * Return the constant value of the static constant represented by the given e
lement. | |
| 503 * | |
| 504 * @param node the node to be used if an error needs to be reported | |
| 505 * @param element the element whose value is to be returned | |
| 506 * @return the constant value of the static constant | |
| 507 */ | |
| 508 EvaluationResultImpl getConstantValue(ASTNode node, Element element) { | |
| 509 if (element is PropertyAccessorElement) { | |
| 510 element = ((element as PropertyAccessorElement)).variable; | |
| 511 } | |
| 512 if (element is VariableElementImpl) { | |
| 513 VariableElementImpl variableElementImpl = element as VariableElementImpl; | |
| 514 EvaluationResultImpl value = variableElementImpl.evaluationResult; | |
| 515 if (variableElementImpl.isConst && value != null) { | |
| 516 return value; | |
| 517 } | |
| 518 } else if (element is ExecutableElement) { | |
| 519 if (((element as ExecutableElement)).isStatic) { | |
| 520 return new ValidResult(element); | |
| 521 } | |
| 522 } else if (element is ClassElement) { | |
| 523 return ValidResult.RESULT_OBJECT; | |
| 524 } | |
| 525 return error(node, null); | |
| 526 } | |
| 527 | |
| 528 /** | |
| 529 * Return the union of the errors encoded in the given results. | |
| 530 * | |
| 531 * @param leftResult the first set of errors, or `null` if there was no previo
us collection | |
| 532 * of errors | |
| 533 * @param rightResult the errors to be added to the collection, or a valid res
ult if there are no | |
| 534 * errors to be added | |
| 535 * @return the union of the errors encoded in the given results | |
| 536 */ | |
| 537 ErrorResult union(ErrorResult leftResult, EvaluationResultImpl rightResult) { | |
| 538 if (rightResult is ErrorResult) { | |
| 539 if (leftResult != null) { | |
| 540 return new ErrorResult.con2(leftResult, rightResult as ErrorResult); | |
| 541 } else { | |
| 542 return rightResult as ErrorResult; | |
| 543 } | |
| 544 } | |
| 545 return leftResult; | |
| 546 } | |
| 547 } | |
| 548 /** | |
| 549 * Instances of the class `DirectedGraph` implement a directed graph in which th
e nodes are | |
| 550 * arbitrary (client provided) objects and edges are represented implicitly. The
graph will allow an | |
| 551 * edge from any node to any other node, including itself, but will not represen
t multiple edges | |
| 552 * between the same pair of nodes. | |
| 553 * | |
| 554 * @param N the type of the nodes in the graph | |
| 555 */ | |
| 556 class DirectedGraph<N> { | |
| 557 | |
| 558 /** | |
| 559 * The table encoding the edges in the graph. An edge is represented by an ent
ry mapping the head | |
| 560 * to a set of tails. Nodes that are not the head of any edge are represented
by an entry mapping | |
| 561 * the node to an empty set of tails. | |
| 562 */ | |
| 563 Map<N, Set<N>> _edges = new Map<N, Set<N>>(); | |
| 564 | |
| 565 /** | |
| 566 * Add an edge from the given head node to the given tail node. Both nodes wil
l be a part of the | |
| 567 * graph after this method is invoked, whether or not they were before. | |
| 568 * | |
| 569 * @param head the node at the head of the edge | |
| 570 * @param tail the node at the tail of the edge | |
| 571 */ | |
| 572 void addEdge(N head, N tail) { | |
| 573 Set<N> tails = _edges[tail]; | |
| 574 if (tails == null) { | |
| 575 _edges[tail] = new Set<N>(); | |
| 576 } | |
| 577 tails = _edges[head]; | |
| 578 if (tails == null) { | |
| 579 tails = new Set<N>(); | |
| 580 _edges[head] = tails; | |
| 581 } | |
| 582 javaSetAdd(tails, tail); | |
| 583 } | |
| 584 | |
| 585 /** | |
| 586 * Add the given node to the set of nodes in the graph. | |
| 587 * | |
| 588 * @param node the node to be added | |
| 589 */ | |
| 590 void addNode(N node) { | |
| 591 Set<N> tails = _edges[node]; | |
| 592 if (tails == null) { | |
| 593 _edges[node] = new Set<N>(); | |
| 594 } | |
| 595 } | |
| 596 | |
| 597 /** | |
| 598 * Return a list of nodes that form a cycle, or `null` if there are no cycles
in this graph. | |
| 599 * | |
| 600 * @return a list of nodes that form a cycle | |
| 601 */ | |
| 602 List<N> findCycle() => null; | |
| 603 | |
| 604 /** | |
| 605 * Return the number of nodes in this graph. | |
| 606 * | |
| 607 * @return the number of nodes in this graph | |
| 608 */ | |
| 609 int get nodeCount => _edges.length; | |
| 610 | |
| 611 /** | |
| 612 * Return a set containing the tails of edges that have the given node as thei
r head. The set will | |
| 613 * be empty if there are no such edges or if the node is not part of the graph
. Clients must not | |
| 614 * modify the returned set. | |
| 615 * | |
| 616 * @param head the node at the head of all of the edges whose tails are to be
returned | |
| 617 * @return a set containing the tails of edges that have the given node as the
ir head | |
| 618 */ | |
| 619 Set<N> getTails(N head) { | |
| 620 Set<N> tails = _edges[head]; | |
| 621 if (tails == null) { | |
| 622 return new Set<N>(); | |
| 623 } | |
| 624 return tails; | |
| 625 } | |
| 626 | |
| 627 /** | |
| 628 * Return `true` if this graph is empty. | |
| 629 * | |
| 630 * @return `true` if this graph is empty | |
| 631 */ | |
| 632 bool get isEmpty => _edges.isEmpty; | |
| 633 | |
| 634 /** | |
| 635 * Remove all of the given nodes from this graph. As a consequence, any edges
for which those | |
| 636 * nodes were either a head or a tail will also be removed. | |
| 637 * | |
| 638 * @param nodes the nodes to be removed | |
| 639 */ | |
| 640 void removeAllNodes(List<N> nodes) { | |
| 641 for (N node in nodes) { | |
| 642 removeNode(node); | |
| 643 } | |
| 644 } | |
| 645 | |
| 646 /** | |
| 647 * Remove the edge from the given head node to the given tail node. If there w
as no such edge then | |
| 648 * the graph will be unmodified: the number of edges will be the same and the
set of nodes will be | |
| 649 * the same (neither node will either be added or removed). | |
| 650 * | |
| 651 * @param head the node at the head of the edge | |
| 652 * @param tail the node at the tail of the edge | |
| 653 * @return `true` if the graph was modified as a result of this operation | |
| 654 */ | |
| 655 void removeEdge(N head, N tail) { | |
| 656 Set<N> tails = _edges[head]; | |
| 657 if (tails != null) { | |
| 658 tails.remove(tail); | |
| 659 } | |
| 660 } | |
| 661 | |
| 662 /** | |
| 663 * Remove the given node from this graph. As a consequence, any edges for whic
h that node was | |
| 664 * either a head or a tail will also be removed. | |
| 665 * | |
| 666 * @param node the node to be removed | |
| 667 */ | |
| 668 void removeNode(N node) { | |
| 669 _edges.remove(node); | |
| 670 for (Set<N> tails in _edges.values) { | |
| 671 tails.remove(node); | |
| 672 } | |
| 673 } | |
| 674 | |
| 675 /** | |
| 676 * Find one node (referred to as a sink node) that has no outgoing edges (that
is, for which there | |
| 677 * are no edges that have that node as the head of the edge) and remove it fro
m this graph. Return | |
| 678 * the node that was removed, or `null` if there are no such nodes either beca
use the graph | |
| 679 * is empty or because every node in the graph has at least one outgoing edge.
As a consequence of | |
| 680 * removing the node from the graph any edges for which that node was a tail w
ill also be removed. | |
| 681 * | |
| 682 * @return the sink node that was removed | |
| 683 */ | |
| 684 N removeSink() { | |
| 685 N sink = findSink(); | |
| 686 if (sink == null) { | |
| 687 return null; | |
| 688 } | |
| 689 removeNode(sink); | |
| 690 return sink; | |
| 691 } | |
| 692 | |
| 693 /** | |
| 694 * Return one node that has no outgoing edges (that is, for which there are no
edges that have | |
| 695 * that node as the head of the edge), or `null` if there are no such nodes. | |
| 696 * | |
| 697 * @return a sink node | |
| 698 */ | |
| 699 N findSink() { | |
| 700 for (N key in _edges.keys) { | |
| 701 if (_edges[key].isEmpty) return key; | |
| 702 } | |
| 703 return null; | |
| 704 } | |
| 705 } | |
| 706 /** | |
| 707 * Instances of the class `ErrorResult` represent the result of evaluating an ex
pression that | |
| 708 * is not a valid compile time constant. | |
| 709 */ | |
| 710 class ErrorResult extends EvaluationResultImpl { | |
| 711 | |
| 712 /** | |
| 713 * The errors that prevent the expression from being a valid compile time cons
tant. | |
| 714 */ | |
| 715 final List<ErrorResult_ErrorData> errorData = new List<ErrorResult_ErrorData>(
); | |
| 716 | |
| 717 /** | |
| 718 * Initialize a newly created result representing the error with the given cod
e reported against | |
| 719 * the given node. | |
| 720 * | |
| 721 * @param node the node against which the error should be reported | |
| 722 * @param errorCode the error code for the error to be generated | |
| 723 */ | |
| 724 ErrorResult.con1(ASTNode node, ErrorCode errorCode) { | |
| 725 errorData.add(new ErrorResult_ErrorData(node, errorCode)); | |
| 726 } | |
| 727 | |
| 728 /** | |
| 729 * Initialize a newly created result to represent the union of the errors in t
he given result | |
| 730 * objects. | |
| 731 * | |
| 732 * @param firstResult the first set of results being merged | |
| 733 * @param secondResult the second set of results being merged | |
| 734 */ | |
| 735 ErrorResult.con2(ErrorResult firstResult, ErrorResult secondResult) { | |
| 736 errorData.addAll(firstResult.errorData); | |
| 737 errorData.addAll(secondResult.errorData); | |
| 738 } | |
| 739 EvaluationResultImpl add(BinaryExpression node, EvaluationResultImpl rightOper
and) => rightOperand.addToError(node, this); | |
| 740 EvaluationResultImpl applyBooleanConversion(ASTNode node) => this; | |
| 741 EvaluationResultImpl bitAnd(BinaryExpression node, EvaluationResultImpl rightO
perand) => rightOperand.bitAndError(node, this); | |
| 742 EvaluationResultImpl bitNot(Expression node) => this; | |
| 743 EvaluationResultImpl bitOr(BinaryExpression node, EvaluationResultImpl rightOp
erand) => rightOperand.bitOrError(node, this); | |
| 744 EvaluationResultImpl bitXor(BinaryExpression node, EvaluationResultImpl rightO
perand) => rightOperand.bitXorError(node, this); | |
| 745 EvaluationResultImpl concatenate(Expression node, EvaluationResultImpl rightOp
erand) => rightOperand.concatenateError(node, this); | |
| 746 EvaluationResultImpl divide(BinaryExpression node, EvaluationResultImpl rightO
perand) => rightOperand.divideError(node, this); | |
| 747 EvaluationResultImpl equalEqual(Expression node, EvaluationResultImpl rightOpe
rand) => rightOperand.equalEqualError(node, this); | |
| 748 bool equalValues(EvaluationResultImpl result) => false; | |
| 749 EvaluationResultImpl greaterThan(BinaryExpression node, EvaluationResultImpl r
ightOperand) => rightOperand.greaterThanError(node, this); | |
| 750 EvaluationResultImpl greaterThanOrEqual(BinaryExpression node, EvaluationResul
tImpl rightOperand) => rightOperand.greaterThanOrEqualError(node, this); | |
| 751 EvaluationResultImpl integerDivide(BinaryExpression node, EvaluationResultImpl
rightOperand) => rightOperand.integerDivideError(node, this); | |
| 752 EvaluationResultImpl integerDivideValid(BinaryExpression node, ValidResult lef
tOperand) => this; | |
| 753 EvaluationResultImpl lessThan(BinaryExpression node, EvaluationResultImpl righ
tOperand) => rightOperand.lessThanError(node, this); | |
| 754 EvaluationResultImpl lessThanOrEqual(BinaryExpression node, EvaluationResultIm
pl rightOperand) => rightOperand.lessThanOrEqualError(node, this); | |
| 755 EvaluationResultImpl logicalAnd(BinaryExpression node, EvaluationResultImpl ri
ghtOperand) => rightOperand.logicalAndError(node, this); | |
| 756 EvaluationResultImpl logicalNot(Expression node) => this; | |
| 757 EvaluationResultImpl logicalOr(BinaryExpression node, EvaluationResultImpl rig
htOperand) => rightOperand.logicalOrError(node, this); | |
| 758 EvaluationResultImpl minus(BinaryExpression node, EvaluationResultImpl rightOp
erand) => rightOperand.minusError(node, this); | |
| 759 EvaluationResultImpl negated(Expression node) => this; | |
| 760 EvaluationResultImpl notEqual(BinaryExpression node, EvaluationResultImpl righ
tOperand) => rightOperand.notEqualError(node, this); | |
| 761 EvaluationResultImpl performToString(ASTNode node) => this; | |
| 762 EvaluationResultImpl remainder(BinaryExpression node, EvaluationResultImpl rig
htOperand) => rightOperand.remainderError(node, this); | |
| 763 EvaluationResultImpl shiftLeft(BinaryExpression node, EvaluationResultImpl rig
htOperand) => rightOperand.shiftLeftError(node, this); | |
| 764 EvaluationResultImpl shiftRight(BinaryExpression node, EvaluationResultImpl ri
ghtOperand) => rightOperand.shiftRightError(node, this); | |
| 765 EvaluationResultImpl times(BinaryExpression node, EvaluationResultImpl rightOp
erand) => rightOperand.timesError(node, this); | |
| 766 EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand
) => new ErrorResult.con2(this, leftOperand); | |
| 767 EvaluationResultImpl addToValid(BinaryExpression node, ValidResult leftOperand
) => this; | |
| 768 EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperan
d) => new ErrorResult.con2(this, leftOperand); | |
| 769 EvaluationResultImpl bitAndValid(BinaryExpression node, ValidResult leftOperan
d) => this; | |
| 770 EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand
) => new ErrorResult.con2(this, leftOperand); | |
| 771 EvaluationResultImpl bitOrValid(BinaryExpression node, ValidResult leftOperand
) => this; | |
| 772 EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperan
d) => new ErrorResult.con2(this, leftOperand); | |
| 773 EvaluationResultImpl bitXorValid(BinaryExpression node, ValidResult leftOperan
d) => this; | |
| 774 EvaluationResultImpl concatenateError(Expression node, ErrorResult leftOperand
) => new ErrorResult.con2(this, leftOperand); | |
| 775 EvaluationResultImpl concatenateValid(Expression node, ValidResult leftOperand
) => this; | |
| 776 EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperan
d) => new ErrorResult.con2(this, leftOperand); | |
| 777 EvaluationResultImpl divideValid(BinaryExpression node, ValidResult leftOperan
d) => this; | |
| 778 EvaluationResultImpl equalEqualError(Expression node, ErrorResult leftOperand)
=> new ErrorResult.con2(this, leftOperand); | |
| 779 EvaluationResultImpl equalEqualValid(Expression node, ValidResult leftOperand)
=> this; | |
| 780 EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftO
perand) => new ErrorResult.con2(this, leftOperand); | |
| 781 EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResul
t leftOperand) => new ErrorResult.con2(this, leftOperand); | |
| 782 EvaluationResultImpl greaterThanOrEqualValid(BinaryExpression node, ValidResul
t leftOperand) => this; | |
| 783 EvaluationResultImpl greaterThanValid(BinaryExpression node, ValidResult leftO
perand) => this; | |
| 784 EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult lef
tOperand) => new ErrorResult.con2(this, leftOperand); | |
| 785 EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOper
and) => new ErrorResult.con2(this, leftOperand); | |
| 786 EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult l
eftOperand) => new ErrorResult.con2(this, leftOperand); | |
| 787 EvaluationResultImpl lessThanOrEqualValid(BinaryExpression node, ValidResult l
eftOperand) => this; | |
| 788 EvaluationResultImpl lessThanValid(BinaryExpression node, ValidResult leftOper
and) => this; | |
| 789 EvaluationResultImpl logicalAndError(BinaryExpression node, ErrorResult leftOp
erand) => new ErrorResult.con2(this, leftOperand); | |
| 790 EvaluationResultImpl logicalAndValid(BinaryExpression node, ValidResult leftOp
erand) => this; | |
| 791 EvaluationResultImpl logicalOrError(BinaryExpression node, ErrorResult leftOpe
rand) => new ErrorResult.con2(this, leftOperand); | |
| 792 EvaluationResultImpl logicalOrValid(BinaryExpression node, ValidResult leftOpe
rand) => this; | |
| 793 EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand
) => new ErrorResult.con2(this, leftOperand); | |
| 794 EvaluationResultImpl minusValid(BinaryExpression node, ValidResult leftOperand
) => this; | |
| 795 EvaluationResultImpl notEqualError(BinaryExpression node, ErrorResult leftOper
and) => new ErrorResult.con2(this, leftOperand); | |
| 796 EvaluationResultImpl notEqualValid(BinaryExpression node, ValidResult leftOper
and) => this; | |
| 797 EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOpe
rand) => new ErrorResult.con2(this, leftOperand); | |
| 798 EvaluationResultImpl remainderValid(BinaryExpression node, ValidResult leftOpe
rand) => this; | |
| 799 EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOpe
rand) => new ErrorResult.con2(this, leftOperand); | |
| 800 EvaluationResultImpl shiftLeftValid(BinaryExpression node, ValidResult leftOpe
rand) => this; | |
| 801 EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOp
erand) => new ErrorResult.con2(this, leftOperand); | |
| 802 EvaluationResultImpl shiftRightValid(BinaryExpression node, ValidResult leftOp
erand) => this; | |
| 803 EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand
) => new ErrorResult.con2(this, leftOperand); | |
| 804 EvaluationResultImpl timesValid(BinaryExpression node, ValidResult leftOperand
) => this; | |
| 805 } | |
| 806 class ErrorResult_ErrorData { | |
| 807 | |
| 808 /** | |
| 809 * The node against which the error should be reported. | |
| 810 */ | |
| 811 ASTNode node; | |
| 812 | |
| 813 /** | |
| 814 * The error code for the error to be generated. | |
| 815 */ | |
| 816 ErrorCode errorCode; | |
| 817 | |
| 818 /** | |
| 819 * Initialize a newly created data holder to represent the error with the give
n code reported | |
| 820 * against the given node. | |
| 821 * | |
| 822 * @param node the node against which the error should be reported | |
| 823 * @param errorCode the error code for the error to be generated | |
| 824 */ | |
| 825 ErrorResult_ErrorData(ASTNode node, ErrorCode errorCode) { | |
| 826 this.node = node; | |
| 827 this.errorCode = errorCode; | |
| 828 } | |
| 829 } | |
| 830 /** | |
| 831 * Instances of the class `InternalResult` represent the result of attempting to
evaluate a | |
| 832 * expression. | |
| 833 */ | |
| 834 abstract class EvaluationResultImpl { | |
| 835 EvaluationResultImpl add(BinaryExpression node, EvaluationResultImpl rightOper
and); | |
| 836 | |
| 837 /** | |
| 838 * Return the result of applying boolean conversion to this result. | |
| 839 * | |
| 840 * @param node the node against which errors should be reported | |
| 841 * @return the result of applying boolean conversion to the given value | |
| 842 */ | |
| 843 EvaluationResultImpl applyBooleanConversion(ASTNode node); | |
| 844 EvaluationResultImpl bitAnd(BinaryExpression node, EvaluationResultImpl rightO
perand); | |
| 845 EvaluationResultImpl bitNot(Expression node); | |
| 846 EvaluationResultImpl bitOr(BinaryExpression node, EvaluationResultImpl rightOp
erand); | |
| 847 EvaluationResultImpl bitXor(BinaryExpression node, EvaluationResultImpl rightO
perand); | |
| 848 EvaluationResultImpl concatenate(Expression node, EvaluationResultImpl rightOp
erand); | |
| 849 EvaluationResultImpl divide(BinaryExpression node, EvaluationResultImpl rightO
perand); | |
| 850 EvaluationResultImpl equalEqual(Expression node, EvaluationResultImpl rightOpe
rand); | |
| 851 bool equalValues(EvaluationResultImpl result); | |
| 852 EvaluationResultImpl greaterThan(BinaryExpression node, EvaluationResultImpl r
ightOperand); | |
| 853 EvaluationResultImpl greaterThanOrEqual(BinaryExpression node, EvaluationResul
tImpl rightOperand); | |
| 854 EvaluationResultImpl integerDivide(BinaryExpression node, EvaluationResultImpl
rightOperand); | |
| 855 EvaluationResultImpl lessThan(BinaryExpression node, EvaluationResultImpl righ
tOperand); | |
| 856 EvaluationResultImpl lessThanOrEqual(BinaryExpression node, EvaluationResultIm
pl rightOperand); | |
| 857 EvaluationResultImpl logicalAnd(BinaryExpression node, EvaluationResultImpl ri
ghtOperand); | |
| 858 EvaluationResultImpl logicalNot(Expression node); | |
| 859 EvaluationResultImpl logicalOr(BinaryExpression node, EvaluationResultImpl rig
htOperand); | |
| 860 EvaluationResultImpl minus(BinaryExpression node, EvaluationResultImpl rightOp
erand); | |
| 861 EvaluationResultImpl negated(Expression node); | |
| 862 EvaluationResultImpl notEqual(BinaryExpression node, EvaluationResultImpl righ
tOperand); | |
| 863 EvaluationResultImpl performToString(ASTNode node); | |
| 864 EvaluationResultImpl remainder(BinaryExpression node, EvaluationResultImpl rig
htOperand); | |
| 865 EvaluationResultImpl shiftLeft(BinaryExpression node, EvaluationResultImpl rig
htOperand); | |
| 866 EvaluationResultImpl shiftRight(BinaryExpression node, EvaluationResultImpl ri
ghtOperand); | |
| 867 EvaluationResultImpl times(BinaryExpression node, EvaluationResultImpl rightOp
erand); | |
| 868 EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand
); | |
| 869 EvaluationResultImpl addToValid(BinaryExpression node, ValidResult leftOperand
); | |
| 870 EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperan
d); | |
| 871 EvaluationResultImpl bitAndValid(BinaryExpression node, ValidResult leftOperan
d); | |
| 872 EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand
); | |
| 873 EvaluationResultImpl bitOrValid(BinaryExpression node, ValidResult leftOperand
); | |
| 874 EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperan
d); | |
| 875 EvaluationResultImpl bitXorValid(BinaryExpression node, ValidResult leftOperan
d); | |
| 876 EvaluationResultImpl concatenateError(Expression node, ErrorResult leftOperand
); | |
| 877 EvaluationResultImpl concatenateValid(Expression node, ValidResult leftOperand
); | |
| 878 EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperan
d); | |
| 879 EvaluationResultImpl divideValid(BinaryExpression node, ValidResult leftOperan
d); | |
| 880 EvaluationResultImpl equalEqualError(Expression node, ErrorResult leftOperand)
; | |
| 881 EvaluationResultImpl equalEqualValid(Expression node, ValidResult leftOperand)
; | |
| 882 EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftO
perand); | |
| 883 EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResul
t leftOperand); | |
| 884 EvaluationResultImpl greaterThanOrEqualValid(BinaryExpression node, ValidResul
t leftOperand); | |
| 885 EvaluationResultImpl greaterThanValid(BinaryExpression node, ValidResult leftO
perand); | |
| 886 EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult lef
tOperand); | |
| 887 EvaluationResultImpl integerDivideValid(BinaryExpression node, ValidResult lef
tOperand); | |
| 888 EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOper
and); | |
| 889 EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult l
eftOperand); | |
| 890 EvaluationResultImpl lessThanOrEqualValid(BinaryExpression node, ValidResult l
eftOperand); | |
| 891 EvaluationResultImpl lessThanValid(BinaryExpression node, ValidResult leftOper
and); | |
| 892 EvaluationResultImpl logicalAndError(BinaryExpression node, ErrorResult leftOp
erand); | |
| 893 EvaluationResultImpl logicalAndValid(BinaryExpression node, ValidResult leftOp
erand); | |
| 894 EvaluationResultImpl logicalOrError(BinaryExpression node, ErrorResult leftOpe
rand); | |
| 895 EvaluationResultImpl logicalOrValid(BinaryExpression node, ValidResult leftOpe
rand); | |
| 896 EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand
); | |
| 897 EvaluationResultImpl minusValid(BinaryExpression node, ValidResult leftOperand
); | |
| 898 EvaluationResultImpl notEqualError(BinaryExpression node, ErrorResult leftOper
and); | |
| 899 EvaluationResultImpl notEqualValid(BinaryExpression node, ValidResult leftOper
and); | |
| 900 EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOpe
rand); | |
| 901 EvaluationResultImpl remainderValid(BinaryExpression node, ValidResult leftOpe
rand); | |
| 902 EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOpe
rand); | |
| 903 EvaluationResultImpl shiftLeftValid(BinaryExpression node, ValidResult leftOpe
rand); | |
| 904 EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOp
erand); | |
| 905 EvaluationResultImpl shiftRightValid(BinaryExpression node, ValidResult leftOp
erand); | |
| 906 EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand
); | |
| 907 EvaluationResultImpl timesValid(BinaryExpression node, ValidResult leftOperand
); | |
| 908 } | |
| 909 /** | |
| 910 * Instances of the class `ReferenceFinder` add reference information for a give
n variable to | |
| 911 * the bi-directional mapping used to order the evaluation of constants. | |
| 912 */ | |
| 913 class ReferenceFinder extends RecursiveASTVisitor<Object> { | |
| 914 | |
| 915 /** | |
| 916 * The element representing the variable whose initializer will be visited. | |
| 917 */ | |
| 918 VariableElement _source; | |
| 919 | |
| 920 /** | |
| 921 * A graph in which the nodes are the constant variables and the edges are fro
m each variable to | |
| 922 * the other constant variables that are referenced in the head's initializer. | |
| 923 */ | |
| 924 DirectedGraph<VariableElement> _referenceGraph; | |
| 925 | |
| 926 /** | |
| 927 * Initialize a newly created reference finder to find references from the giv
en variable to other | |
| 928 * variables and to add those references to the given graph. | |
| 929 * | |
| 930 * @param source the element representing the variable whose initializer will
be visited | |
| 931 * @param referenceGraph a graph recording which variables (heads) reference w
hich other variables | |
| 932 * (tails) in their initializers | |
| 933 */ | |
| 934 ReferenceFinder(VariableElement source, DirectedGraph<VariableElement> referen
ceGraph) { | |
| 935 this._source = source; | |
| 936 this._referenceGraph = referenceGraph; | |
| 937 } | |
| 938 Object visitSimpleIdentifier(SimpleIdentifier node) { | |
| 939 Element element = node.staticElement; | |
| 940 if (element is PropertyAccessorElement) { | |
| 941 element = ((element as PropertyAccessorElement)).variable; | |
| 942 } | |
| 943 if (element is VariableElement) { | |
| 944 VariableElement variable = element as VariableElement; | |
| 945 if (variable.isConst) { | |
| 946 _referenceGraph.addEdge(_source, variable); | |
| 947 } | |
| 948 } | |
| 949 return null; | |
| 950 } | |
| 951 } | |
| 952 /** | |
| 953 * Instances of the class `ValidResult` represent the result of attempting to ev
aluate a valid | |
| 954 * compile time constant expression. | |
| 955 */ | |
| 956 class ValidResult extends EvaluationResultImpl { | |
| 957 | |
| 958 /** | |
| 959 * A result object representing the value 'false'. | |
| 960 */ | |
| 961 static ValidResult RESULT_FALSE = new ValidResult(false); | |
| 962 | |
| 963 /** | |
| 964 * A result object representing the an object without specific type on which n
o further operations | |
| 965 * can be performed. | |
| 966 */ | |
| 967 static ValidResult RESULT_DYNAMIC = new ValidResult(null); | |
| 968 | |
| 969 /** | |
| 970 * A result object representing the an arbitrary integer on which no further o
perations can be | |
| 971 * performed. | |
| 972 */ | |
| 973 static ValidResult RESULT_INT = new ValidResult(0); | |
| 974 | |
| 975 /** | |
| 976 * A result object representing the `null` value. | |
| 977 */ | |
| 978 static ValidResult RESULT_NULL = new ValidResult(null); | |
| 979 | |
| 980 /** | |
| 981 * A result object representing the an arbitrary numeric on which no further o
perations can be | |
| 982 * performed. | |
| 983 */ | |
| 984 static ValidResult RESULT_NUM = new ValidResult(null); | |
| 985 | |
| 986 /** | |
| 987 * A result object representing the an arbitrary boolean on which no further o
perations can be | |
| 988 * performed. | |
| 989 */ | |
| 990 static ValidResult RESULT_BOOL = new ValidResult(null); | |
| 991 | |
| 992 /** | |
| 993 * A result object representing the an arbitrary object on which no further op
erations can be | |
| 994 * performed. | |
| 995 */ | |
| 996 static ValidResult RESULT_OBJECT = new ValidResult(new Object()); | |
| 997 | |
| 998 /** | |
| 999 * A result object representing the an arbitrary symbol on which no further op
erations can be | |
| 1000 * performed. | |
| 1001 */ | |
| 1002 static ValidResult RESULT_SYMBOL = new ValidResult(new Object()); | |
| 1003 | |
| 1004 /** | |
| 1005 * A result object representing the an arbitrary string on which no further op
erations can be | |
| 1006 * performed. | |
| 1007 */ | |
| 1008 static ValidResult RESULT_STRING = new ValidResult("<string>"); | |
| 1009 | |
| 1010 /** | |
| 1011 * A result object representing the value 'true'. | |
| 1012 */ | |
| 1013 static ValidResult RESULT_TRUE = new ValidResult(true); | |
| 1014 | |
| 1015 /** | |
| 1016 * The value of the expression. | |
| 1017 */ | |
| 1018 Object value; | |
| 1019 | |
| 1020 /** | |
| 1021 * Initialize a newly created result to represent the given value. | |
| 1022 * | |
| 1023 * @param value the value of the expression | |
| 1024 */ | |
| 1025 ValidResult(Object value) { | |
| 1026 this.value = value; | |
| 1027 } | |
| 1028 EvaluationResultImpl add(BinaryExpression node, EvaluationResultImpl rightOper
and) => rightOperand.addToValid(node, this); | |
| 1029 | |
| 1030 /** | |
| 1031 * Return the result of applying boolean conversion to this result. | |
| 1032 * | |
| 1033 * @param node the node against which errors should be reported | |
| 1034 * @return the result of applying boolean conversion to the given value | |
| 1035 */ | |
| 1036 EvaluationResultImpl applyBooleanConversion(ASTNode node) => booleanConversion
(node, value); | |
| 1037 EvaluationResultImpl bitAnd(BinaryExpression node, EvaluationResultImpl rightO
perand) => rightOperand.bitAndValid(node, this); | |
| 1038 EvaluationResultImpl bitNot(Expression node) { | |
| 1039 if (isSomeInt) { | |
| 1040 return RESULT_INT; | |
| 1041 } | |
| 1042 if (value == null) { | |
| 1043 return error(node); | |
| 1044 } else if (value is int) { | |
| 1045 return valueOf(~((value as int))); | |
| 1046 } | |
| 1047 return error(node); | |
| 1048 } | |
| 1049 EvaluationResultImpl bitOr(BinaryExpression node, EvaluationResultImpl rightOp
erand) => rightOperand.bitOrValid(node, this); | |
| 1050 EvaluationResultImpl bitXor(BinaryExpression node, EvaluationResultImpl rightO
perand) => rightOperand.bitXorValid(node, this); | |
| 1051 EvaluationResultImpl concatenate(Expression node, EvaluationResultImpl rightOp
erand) => rightOperand.concatenateValid(node, this); | |
| 1052 EvaluationResultImpl divide(BinaryExpression node, EvaluationResultImpl rightO
perand) => rightOperand.divideValid(node, this); | |
| 1053 EvaluationResultImpl equalEqual(Expression node, EvaluationResultImpl rightOpe
rand) => rightOperand.equalEqualValid(node, this); | |
| 1054 bool equalValues(EvaluationResultImpl result) => identical(equalEqual(null, re
sult), RESULT_TRUE); | |
| 1055 EvaluationResultImpl greaterThan(BinaryExpression node, EvaluationResultImpl r
ightOperand) => rightOperand.greaterThanValid(node, this); | |
| 1056 EvaluationResultImpl greaterThanOrEqual(BinaryExpression node, EvaluationResul
tImpl rightOperand) => rightOperand.greaterThanOrEqualValid(node, this); | |
| 1057 EvaluationResultImpl integerDivide(BinaryExpression node, EvaluationResultImpl
rightOperand) => rightOperand.integerDivideValid(node, this); | |
| 1058 EvaluationResultImpl lessThan(BinaryExpression node, EvaluationResultImpl righ
tOperand) => rightOperand.lessThanValid(node, this); | |
| 1059 EvaluationResultImpl lessThanOrEqual(BinaryExpression node, EvaluationResultIm
pl rightOperand) => rightOperand.lessThanOrEqualValid(node, this); | |
| 1060 EvaluationResultImpl logicalAnd(BinaryExpression node, EvaluationResultImpl ri
ghtOperand) => rightOperand.logicalAndValid(node, this); | |
| 1061 EvaluationResultImpl logicalNot(Expression node) { | |
| 1062 if (isSomeBool) { | |
| 1063 return RESULT_BOOL; | |
| 1064 } | |
| 1065 if (value == null) { | |
| 1066 return RESULT_TRUE; | |
| 1067 } else if (value is bool) { | |
| 1068 return ((value as bool)) ? RESULT_FALSE : RESULT_TRUE; | |
| 1069 } | |
| 1070 return error(node); | |
| 1071 } | |
| 1072 EvaluationResultImpl logicalOr(BinaryExpression node, EvaluationResultImpl rig
htOperand) => rightOperand.logicalOrValid(node, this); | |
| 1073 EvaluationResultImpl minus(BinaryExpression node, EvaluationResultImpl rightOp
erand) => rightOperand.minusValid(node, this); | |
| 1074 EvaluationResultImpl negated(Expression node) { | |
| 1075 if (isSomeNum) { | |
| 1076 return RESULT_INT; | |
| 1077 } | |
| 1078 if (value == null) { | |
| 1079 return error(node); | |
| 1080 } else if (value is int) { | |
| 1081 return valueOf(-((value as int))); | |
| 1082 } else if (value is double) { | |
| 1083 return valueOf3(-((value as double))); | |
| 1084 } | |
| 1085 return error(node); | |
| 1086 } | |
| 1087 EvaluationResultImpl notEqual(BinaryExpression node, EvaluationResultImpl righ
tOperand) => rightOperand.notEqualValid(node, this); | |
| 1088 EvaluationResultImpl performToString(ASTNode node) { | |
| 1089 if (value == null) { | |
| 1090 return valueOf4("null"); | |
| 1091 } else if (value is bool) { | |
| 1092 return valueOf4(((value as bool)).toString()); | |
| 1093 } else if (value is int) { | |
| 1094 return valueOf4(((value as int)).toString()); | |
| 1095 } else if (value is double) { | |
| 1096 return valueOf4(((value as double)).toString()); | |
| 1097 } else if (value is String) { | |
| 1098 return this; | |
| 1099 } else if (isSomeBool) { | |
| 1100 return valueOf4("<some bool>"); | |
| 1101 } else if (isSomeInt) { | |
| 1102 return valueOf4("<some int>"); | |
| 1103 } else if (isSomeNum) { | |
| 1104 return valueOf4("<some num>"); | |
| 1105 } | |
| 1106 return error(node); | |
| 1107 } | |
| 1108 EvaluationResultImpl remainder(BinaryExpression node, EvaluationResultImpl rig
htOperand) => rightOperand.remainderValid(node, this); | |
| 1109 EvaluationResultImpl shiftLeft(BinaryExpression node, EvaluationResultImpl rig
htOperand) => rightOperand.shiftLeftValid(node, this); | |
| 1110 EvaluationResultImpl shiftRight(BinaryExpression node, EvaluationResultImpl ri
ghtOperand) => rightOperand.shiftRightValid(node, this); | |
| 1111 EvaluationResultImpl times(BinaryExpression node, EvaluationResultImpl rightOp
erand) => rightOperand.timesValid(node, this); | |
| 1112 String toString() { | |
| 1113 if (value == null) { | |
| 1114 return "null"; | |
| 1115 } | |
| 1116 return value.toString(); | |
| 1117 } | |
| 1118 EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand
) => leftOperand; | |
| 1119 EvaluationResultImpl addToValid(BinaryExpression node, ValidResult leftOperand
) { | |
| 1120 if (!isAnyNum || !leftOperand.isAnyNum) { | |
| 1121 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); | |
| 1122 } | |
| 1123 if (isSomeInt || leftOperand.isSomeInt) { | |
| 1124 return RESULT_INT; | |
| 1125 } else if (isSomeNum || leftOperand.isSomeNum) { | |
| 1126 return RESULT_NUM; | |
| 1127 } | |
| 1128 Object leftValue = leftOperand.value; | |
| 1129 if (leftValue == null) { | |
| 1130 return error(node.leftOperand); | |
| 1131 } else if (value == null) { | |
| 1132 return error(node.rightOperand); | |
| 1133 } else if (leftValue is int) { | |
| 1134 if (value is int) { | |
| 1135 return valueOf(((leftValue as int)) + (value as int)); | |
| 1136 } else if (value is double) { | |
| 1137 return valueOf3(((leftValue as int)).toDouble() + ((value as double))); | |
| 1138 } | |
| 1139 } else if (leftValue is double) { | |
| 1140 if (value is int) { | |
| 1141 return valueOf3(((leftValue as double)) + ((value as int)).toDouble()); | |
| 1142 } else if (value is double) { | |
| 1143 return valueOf3(((leftValue as double)) + ((value as double))); | |
| 1144 } | |
| 1145 } else if (leftValue is String) { | |
| 1146 if (value is String) { | |
| 1147 return valueOf4("${((leftValue as String))}${((value as String))}"); | |
| 1148 } | |
| 1149 } | |
| 1150 return error(node); | |
| 1151 } | |
| 1152 EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperan
d) => leftOperand; | |
| 1153 EvaluationResultImpl bitAndValid(BinaryExpression node, ValidResult leftOperan
d) { | |
| 1154 if (!isAnyInt || !leftOperand.isAnyInt) { | |
| 1155 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT); | |
| 1156 } | |
| 1157 if (isSomeInt || leftOperand.isSomeInt) { | |
| 1158 return RESULT_INT; | |
| 1159 } | |
| 1160 Object leftValue = leftOperand.value; | |
| 1161 if (leftValue == null) { | |
| 1162 return error(node.leftOperand); | |
| 1163 } else if (value == null) { | |
| 1164 return error(node.rightOperand); | |
| 1165 } else if (leftValue is int) { | |
| 1166 if (value is int) { | |
| 1167 return valueOf(((leftValue as int)) & (value as int)); | |
| 1168 } | |
| 1169 return error(node.leftOperand); | |
| 1170 } | |
| 1171 if (value is int) { | |
| 1172 return error(node.rightOperand); | |
| 1173 } | |
| 1174 return union(error(node.leftOperand), error(node.rightOperand)); | |
| 1175 } | |
| 1176 EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand
) => leftOperand; | |
| 1177 EvaluationResultImpl bitOrValid(BinaryExpression node, ValidResult leftOperand
) { | |
| 1178 if (!isAnyInt || !leftOperand.isAnyInt) { | |
| 1179 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT); | |
| 1180 } | |
| 1181 if (isSomeInt || leftOperand.isSomeInt) { | |
| 1182 return RESULT_INT; | |
| 1183 } | |
| 1184 Object leftValue = leftOperand.value; | |
| 1185 if (leftValue == null) { | |
| 1186 return error(node.leftOperand); | |
| 1187 } else if (value == null) { | |
| 1188 return error(node.rightOperand); | |
| 1189 } else if (leftValue is int) { | |
| 1190 if (value is int) { | |
| 1191 return valueOf(((leftValue as int)) | (value as int)); | |
| 1192 } | |
| 1193 return error(node.leftOperand); | |
| 1194 } | |
| 1195 if (value is int) { | |
| 1196 return error(node.rightOperand); | |
| 1197 } | |
| 1198 return union(error(node.leftOperand), error(node.rightOperand)); | |
| 1199 } | |
| 1200 EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperan
d) => leftOperand; | |
| 1201 EvaluationResultImpl bitXorValid(BinaryExpression node, ValidResult leftOperan
d) { | |
| 1202 if (!isAnyInt || !leftOperand.isAnyInt) { | |
| 1203 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT); | |
| 1204 } | |
| 1205 if (isSomeInt || leftOperand.isSomeInt) { | |
| 1206 return RESULT_INT; | |
| 1207 } | |
| 1208 Object leftValue = leftOperand.value; | |
| 1209 if (leftValue == null) { | |
| 1210 return error(node.leftOperand); | |
| 1211 } else if (value == null) { | |
| 1212 return error(node.rightOperand); | |
| 1213 } else if (leftValue is int) { | |
| 1214 if (value is int) { | |
| 1215 return valueOf(((leftValue as int)) ^ (value as int)); | |
| 1216 } | |
| 1217 return error(node.leftOperand); | |
| 1218 } | |
| 1219 if (value is int) { | |
| 1220 return error(node.rightOperand); | |
| 1221 } | |
| 1222 return union(error(node.leftOperand), error(node.rightOperand)); | |
| 1223 } | |
| 1224 EvaluationResultImpl concatenateError(Expression node, ErrorResult leftOperand
) => leftOperand; | |
| 1225 EvaluationResultImpl concatenateValid(Expression node, ValidResult leftOperand
) { | |
| 1226 Object leftValue = leftOperand.value; | |
| 1227 if (leftValue is String && value is String) { | |
| 1228 return valueOf4("${((leftValue as String))}${((value as String))}"); | |
| 1229 } | |
| 1230 return error(node); | |
| 1231 } | |
| 1232 EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperan
d) => leftOperand; | |
| 1233 EvaluationResultImpl divideValid(BinaryExpression node, ValidResult leftOperan
d) { | |
| 1234 if (!isAnyNum || !leftOperand.isAnyNum) { | |
| 1235 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); | |
| 1236 } | |
| 1237 if (isSomeNum || leftOperand.isSomeNum) { | |
| 1238 return RESULT_NUM; | |
| 1239 } | |
| 1240 Object leftValue = leftOperand.value; | |
| 1241 if (leftValue == null) { | |
| 1242 return error(node.leftOperand); | |
| 1243 } else if (value == null) { | |
| 1244 return error(node.rightOperand); | |
| 1245 } else if (leftValue is int) { | |
| 1246 if (value is int) { | |
| 1247 if (((value as int)) == 0) { | |
| 1248 return valueOf3(((leftValue as int)).toDouble() / ((value as int)).toD
ouble()); | |
| 1249 } | |
| 1250 return valueOf(((leftValue as int)) ~/ (value as int)); | |
| 1251 } else if (value is double) { | |
| 1252 return valueOf3(((leftValue as int)).toDouble() / ((value as double))); | |
| 1253 } | |
| 1254 } else if (leftValue is double) { | |
| 1255 if (value is int) { | |
| 1256 return valueOf3(((leftValue as double)) / ((value as int)).toDouble()); | |
| 1257 } else if (value is double) { | |
| 1258 return valueOf3(((leftValue as double)) / ((value as double))); | |
| 1259 } | |
| 1260 } | |
| 1261 return error(node); | |
| 1262 } | |
| 1263 EvaluationResultImpl equalEqualError(Expression node, ErrorResult leftOperand)
=> leftOperand; | |
| 1264 EvaluationResultImpl equalEqualValid(Expression node, ValidResult leftOperand)
{ | |
| 1265 if (node is BinaryExpression) { | |
| 1266 if (!isAnyNullBoolNumString || !leftOperand.isAnyNullBoolNumString) { | |
| 1267 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING
); | |
| 1268 } | |
| 1269 } | |
| 1270 Object leftValue = leftOperand.value; | |
| 1271 if (leftValue == null) { | |
| 1272 return valueOf2(value == null); | |
| 1273 } else if (leftValue is bool) { | |
| 1274 if (value is bool) { | |
| 1275 return valueOf2(identical(leftValue as bool, value as bool)); | |
| 1276 } | |
| 1277 return RESULT_FALSE; | |
| 1278 } else if (leftValue is int) { | |
| 1279 if (value is int) { | |
| 1280 return valueOf2(((leftValue as int)) == value); | |
| 1281 } else if (value is double) { | |
| 1282 return valueOf2(toDouble(leftValue as int) == value); | |
| 1283 } | |
| 1284 return RESULT_FALSE; | |
| 1285 } else if (leftValue is double) { | |
| 1286 if (value is int) { | |
| 1287 return valueOf2(((leftValue as double)) == toDouble(value as int)); | |
| 1288 } else if (value is double) { | |
| 1289 return valueOf2(((leftValue as double)) == value); | |
| 1290 } | |
| 1291 return RESULT_FALSE; | |
| 1292 } else if (leftValue is String) { | |
| 1293 if (value is String) { | |
| 1294 return valueOf2(((leftValue as String)) == value); | |
| 1295 } | |
| 1296 return RESULT_FALSE; | |
| 1297 } | |
| 1298 return RESULT_FALSE; | |
| 1299 } | |
| 1300 EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftO
perand) => leftOperand; | |
| 1301 EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResul
t leftOperand) => leftOperand; | |
| 1302 EvaluationResultImpl greaterThanOrEqualValid(BinaryExpression node, ValidResul
t leftOperand) { | |
| 1303 if (!isAnyNum || !leftOperand.isAnyNum) { | |
| 1304 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); | |
| 1305 } | |
| 1306 if (isSomeNum || leftOperand.isSomeNum) { | |
| 1307 return RESULT_BOOL; | |
| 1308 } | |
| 1309 Object leftValue = leftOperand.value; | |
| 1310 if (leftValue == null) { | |
| 1311 return error(node.leftOperand); | |
| 1312 } else if (value == null) { | |
| 1313 return error(node.rightOperand); | |
| 1314 } else if (leftValue is int) { | |
| 1315 if (value is int) { | |
| 1316 return valueOf2(((leftValue as int)).compareTo(value as int) >= 0); | |
| 1317 } else if (value is double) { | |
| 1318 return valueOf2(((leftValue as int)).toDouble() >= ((value as double))); | |
| 1319 } | |
| 1320 } else if (leftValue is double) { | |
| 1321 if (value is int) { | |
| 1322 return valueOf2(((leftValue as double)) >= ((value as int)).toDouble()); | |
| 1323 } else if (value is double) { | |
| 1324 return valueOf2(((leftValue as double)) >= ((value as double))); | |
| 1325 } | |
| 1326 } | |
| 1327 return error(node); | |
| 1328 } | |
| 1329 EvaluationResultImpl greaterThanValid(BinaryExpression node, ValidResult leftO
perand) { | |
| 1330 if (!isAnyNum || !leftOperand.isAnyNum) { | |
| 1331 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); | |
| 1332 } | |
| 1333 if (isSomeNum || leftOperand.isSomeNum) { | |
| 1334 return RESULT_BOOL; | |
| 1335 } | |
| 1336 Object leftValue = leftOperand.value; | |
| 1337 if (leftValue == null) { | |
| 1338 return error(node.leftOperand); | |
| 1339 } else if (value == null) { | |
| 1340 return error(node.rightOperand); | |
| 1341 } else if (leftValue is int) { | |
| 1342 if (value is int) { | |
| 1343 return valueOf2(((leftValue as int)).compareTo(value as int) > 0); | |
| 1344 } else if (value is double) { | |
| 1345 return valueOf2(((leftValue as int)).toDouble() > ((value as double))); | |
| 1346 } | |
| 1347 } else if (leftValue is double) { | |
| 1348 if (value is int) { | |
| 1349 return valueOf2(((leftValue as double)) > ((value as int)).toDouble()); | |
| 1350 } else if (value is double) { | |
| 1351 return valueOf2(((leftValue as double)) > ((value as double))); | |
| 1352 } | |
| 1353 } | |
| 1354 return error(node); | |
| 1355 } | |
| 1356 EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult lef
tOperand) => leftOperand; | |
| 1357 EvaluationResultImpl integerDivideValid(BinaryExpression node, ValidResult lef
tOperand) { | |
| 1358 if (!isAnyNum || !leftOperand.isAnyNum) { | |
| 1359 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); | |
| 1360 } | |
| 1361 if (isSomeNum || leftOperand.isSomeNum) { | |
| 1362 return RESULT_INT; | |
| 1363 } | |
| 1364 Object leftValue = leftOperand.value; | |
| 1365 if (leftValue == null) { | |
| 1366 return error(node.leftOperand); | |
| 1367 } else if (value == null) { | |
| 1368 return error(node.rightOperand); | |
| 1369 } else if (leftValue is int) { | |
| 1370 if (value is int) { | |
| 1371 if (((value as int)) == 0) { | |
| 1372 return error2(node, CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE); | |
| 1373 } | |
| 1374 return valueOf(((leftValue as int)) ~/ (value as int)); | |
| 1375 } else if (value is double) { | |
| 1376 double result = ((leftValue as int)).toDouble() / ((value as double)); | |
| 1377 return valueOf(result.toInt()); | |
| 1378 } | |
| 1379 } else if (leftValue is double) { | |
| 1380 if (value is int) { | |
| 1381 double result = ((leftValue as double)) / ((value as int)).toDouble(); | |
| 1382 return valueOf(result.toInt()); | |
| 1383 } else if (value is double) { | |
| 1384 double result = ((leftValue as double)) / ((value as double)); | |
| 1385 return valueOf(result.toInt()); | |
| 1386 } | |
| 1387 } | |
| 1388 return error(node); | |
| 1389 } | |
| 1390 EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOper
and) => leftOperand; | |
| 1391 EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult l
eftOperand) => leftOperand; | |
| 1392 EvaluationResultImpl lessThanOrEqualValid(BinaryExpression node, ValidResult l
eftOperand) { | |
| 1393 if (!isAnyNum || !leftOperand.isAnyNum) { | |
| 1394 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); | |
| 1395 } | |
| 1396 if (isSomeNum || leftOperand.isSomeNum) { | |
| 1397 return RESULT_BOOL; | |
| 1398 } | |
| 1399 Object leftValue = leftOperand.value; | |
| 1400 if (leftValue == null) { | |
| 1401 return error(node.leftOperand); | |
| 1402 } else if (value == null) { | |
| 1403 return error(node.rightOperand); | |
| 1404 } else if (leftValue is int) { | |
| 1405 if (value is int) { | |
| 1406 return valueOf2(((leftValue as int)).compareTo(value as int) <= 0); | |
| 1407 } else if (value is double) { | |
| 1408 return valueOf2(((leftValue as int)).toDouble() <= ((value as double))); | |
| 1409 } | |
| 1410 } else if (leftValue is double) { | |
| 1411 if (value is int) { | |
| 1412 return valueOf2(((leftValue as double)) <= ((value as int)).toDouble()); | |
| 1413 } else if (value is double) { | |
| 1414 return valueOf2(((leftValue as double)) <= ((value as double))); | |
| 1415 } | |
| 1416 } | |
| 1417 return error(node); | |
| 1418 } | |
| 1419 EvaluationResultImpl lessThanValid(BinaryExpression node, ValidResult leftOper
and) { | |
| 1420 if (!isAnyNum || !leftOperand.isAnyNum) { | |
| 1421 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); | |
| 1422 } | |
| 1423 if (isSomeNum || leftOperand.isSomeNum) { | |
| 1424 return RESULT_BOOL; | |
| 1425 } | |
| 1426 Object leftValue = leftOperand.value; | |
| 1427 if (leftValue == null) { | |
| 1428 return error(node.leftOperand); | |
| 1429 } else if (value == null) { | |
| 1430 return error(node.rightOperand); | |
| 1431 } else if (leftValue is int) { | |
| 1432 if (value is int) { | |
| 1433 return valueOf2(((leftValue as int)).compareTo(value as int) < 0); | |
| 1434 } else if (value is double) { | |
| 1435 return valueOf2(((leftValue as int)).toDouble() < ((value as double))); | |
| 1436 } | |
| 1437 } else if (leftValue is double) { | |
| 1438 if (value is int) { | |
| 1439 return valueOf2(((leftValue as double)) < ((value as int)).toDouble()); | |
| 1440 } else if (value is double) { | |
| 1441 return valueOf2(((leftValue as double)) < ((value as double))); | |
| 1442 } | |
| 1443 } | |
| 1444 return error(node); | |
| 1445 } | |
| 1446 EvaluationResultImpl logicalAndError(BinaryExpression node, ErrorResult leftOp
erand) => leftOperand; | |
| 1447 EvaluationResultImpl logicalAndValid(BinaryExpression node, ValidResult leftOp
erand) { | |
| 1448 if (!isAnyBool || !leftOperand.isAnyBool) { | |
| 1449 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL); | |
| 1450 } | |
| 1451 if (isSomeBool || leftOperand.isSomeBool) { | |
| 1452 return RESULT_BOOL; | |
| 1453 } | |
| 1454 Object leftValue = leftOperand.value; | |
| 1455 if (leftValue is bool) { | |
| 1456 if (leftValue as bool) { | |
| 1457 return booleanConversion(node.rightOperand, value); | |
| 1458 } | |
| 1459 return RESULT_FALSE; | |
| 1460 } | |
| 1461 return error(node); | |
| 1462 } | |
| 1463 EvaluationResultImpl logicalOrError(BinaryExpression node, ErrorResult leftOpe
rand) => leftOperand; | |
| 1464 EvaluationResultImpl logicalOrValid(BinaryExpression node, ValidResult leftOpe
rand) { | |
| 1465 if (!isAnyBool || !leftOperand.isAnyBool) { | |
| 1466 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL); | |
| 1467 } | |
| 1468 if (isSomeBool || leftOperand.isSomeBool) { | |
| 1469 return RESULT_BOOL; | |
| 1470 } | |
| 1471 Object leftValue = leftOperand.value; | |
| 1472 if (leftValue is bool && ((leftValue as bool))) { | |
| 1473 return RESULT_TRUE; | |
| 1474 } | |
| 1475 return booleanConversion(node.rightOperand, value); | |
| 1476 } | |
| 1477 EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand
) => leftOperand; | |
| 1478 EvaluationResultImpl minusValid(BinaryExpression node, ValidResult leftOperand
) { | |
| 1479 if (!isAnyNum || !leftOperand.isAnyNum) { | |
| 1480 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); | |
| 1481 } | |
| 1482 if (isSomeInt || leftOperand.isSomeInt) { | |
| 1483 return RESULT_INT; | |
| 1484 } else if (isSomeNum || leftOperand.isSomeNum) { | |
| 1485 return RESULT_NUM; | |
| 1486 } | |
| 1487 Object leftValue = leftOperand.value; | |
| 1488 if (leftValue == null) { | |
| 1489 return error(node.leftOperand); | |
| 1490 } else if (value == null) { | |
| 1491 return error(node.rightOperand); | |
| 1492 } else if (leftValue is int) { | |
| 1493 if (value is int) { | |
| 1494 return valueOf(((leftValue as int)) - (value as int)); | |
| 1495 } else if (value is double) { | |
| 1496 return valueOf3(((leftValue as int)).toDouble() - ((value as double))); | |
| 1497 } | |
| 1498 } else if (leftValue is double) { | |
| 1499 if (value is int) { | |
| 1500 return valueOf3(((leftValue as double)) - ((value as int)).toDouble()); | |
| 1501 } else if (value is double) { | |
| 1502 return valueOf3(((leftValue as double)) - ((value as double))); | |
| 1503 } | |
| 1504 } | |
| 1505 return error(node); | |
| 1506 } | |
| 1507 EvaluationResultImpl notEqualError(BinaryExpression node, ErrorResult leftOper
and) => leftOperand; | |
| 1508 EvaluationResultImpl notEqualValid(BinaryExpression node, ValidResult leftOper
and) { | |
| 1509 if (!isAnyNullBoolNumString || !leftOperand.isAnyNullBoolNumString) { | |
| 1510 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING); | |
| 1511 } | |
| 1512 Object leftValue = leftOperand.value; | |
| 1513 if (leftValue == null) { | |
| 1514 return valueOf2(value != null); | |
| 1515 } else if (leftValue is bool) { | |
| 1516 if (value is bool) { | |
| 1517 return valueOf2(((leftValue as bool)) != ((value as bool))); | |
| 1518 } | |
| 1519 return RESULT_TRUE; | |
| 1520 } else if (leftValue is int) { | |
| 1521 if (value is int) { | |
| 1522 return valueOf2(((leftValue as int)) != value); | |
| 1523 } else if (value is double) { | |
| 1524 return valueOf2(toDouble(leftValue as int) != value); | |
| 1525 } | |
| 1526 return RESULT_TRUE; | |
| 1527 } else if (leftValue is double) { | |
| 1528 if (value is int) { | |
| 1529 return valueOf2(((leftValue as double)) != toDouble(value as int)); | |
| 1530 } else if (value is double) { | |
| 1531 return valueOf2(((leftValue as double)) != value); | |
| 1532 } | |
| 1533 return RESULT_TRUE; | |
| 1534 } else if (leftValue is String) { | |
| 1535 if (value is String) { | |
| 1536 return valueOf2(((leftValue as String)) != value); | |
| 1537 } | |
| 1538 return RESULT_TRUE; | |
| 1539 } | |
| 1540 return RESULT_TRUE; | |
| 1541 } | |
| 1542 EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOpe
rand) => leftOperand; | |
| 1543 EvaluationResultImpl remainderValid(BinaryExpression node, ValidResult leftOpe
rand) { | |
| 1544 if (!isAnyNum || !leftOperand.isAnyNum) { | |
| 1545 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); | |
| 1546 } | |
| 1547 if (isSomeInt || leftOperand.isSomeInt) { | |
| 1548 return RESULT_INT; | |
| 1549 } else if (isSomeNum || leftOperand.isSomeNum) { | |
| 1550 return RESULT_NUM; | |
| 1551 } | |
| 1552 Object leftValue = leftOperand.value; | |
| 1553 if (leftValue == null) { | |
| 1554 return error(node.leftOperand); | |
| 1555 } else if (value == null) { | |
| 1556 return error(node.rightOperand); | |
| 1557 } else if (leftValue is int) { | |
| 1558 if (value is int) { | |
| 1559 if (((value as int)) == 0) { | |
| 1560 return valueOf3(((leftValue as int)).toDouble() % ((value as int)).toD
ouble()); | |
| 1561 } | |
| 1562 return valueOf(((leftValue as int)).remainder(value as int)); | |
| 1563 } else if (value is double) { | |
| 1564 return valueOf3(((leftValue as int)).toDouble() % ((value as double))); | |
| 1565 } | |
| 1566 } else if (leftValue is double) { | |
| 1567 if (value is int) { | |
| 1568 return valueOf3(((leftValue as double)) % ((value as int)).toDouble()); | |
| 1569 } else if (value is double) { | |
| 1570 return valueOf3(((leftValue as double)) % ((value as double))); | |
| 1571 } | |
| 1572 } | |
| 1573 return error(node); | |
| 1574 } | |
| 1575 EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOpe
rand) => leftOperand; | |
| 1576 EvaluationResultImpl shiftLeftValid(BinaryExpression node, ValidResult leftOpe
rand) { | |
| 1577 if (!isAnyInt || !leftOperand.isAnyInt) { | |
| 1578 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT); | |
| 1579 } | |
| 1580 if (isSomeInt || leftOperand.isSomeInt) { | |
| 1581 return RESULT_INT; | |
| 1582 } | |
| 1583 Object leftValue = leftOperand.value; | |
| 1584 if (leftValue == null) { | |
| 1585 return error(node.leftOperand); | |
| 1586 } else if (value == null) { | |
| 1587 return error(node.rightOperand); | |
| 1588 } else if (leftValue is int) { | |
| 1589 if (value is int) { | |
| 1590 return RESULT_INT; | |
| 1591 } | |
| 1592 return error(node.rightOperand); | |
| 1593 } | |
| 1594 if (value is int) { | |
| 1595 return error(node.leftOperand); | |
| 1596 } | |
| 1597 return union(error(node.leftOperand), error(node.rightOperand)); | |
| 1598 } | |
| 1599 EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOp
erand) => leftOperand; | |
| 1600 EvaluationResultImpl shiftRightValid(BinaryExpression node, ValidResult leftOp
erand) { | |
| 1601 if (!isAnyInt || !leftOperand.isAnyInt) { | |
| 1602 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT); | |
| 1603 } | |
| 1604 if (isSomeInt || leftOperand.isSomeInt) { | |
| 1605 return RESULT_INT; | |
| 1606 } | |
| 1607 Object leftValue = leftOperand.value; | |
| 1608 if (leftValue == null) { | |
| 1609 return error(node.leftOperand); | |
| 1610 } else if (value == null) { | |
| 1611 return error(node.rightOperand); | |
| 1612 } else if (leftValue is int) { | |
| 1613 if (value is int) { | |
| 1614 return valueOf(((leftValue as int)) >> ((value as int))); | |
| 1615 } | |
| 1616 return error(node.rightOperand); | |
| 1617 } | |
| 1618 if (value is int) { | |
| 1619 return error(node.leftOperand); | |
| 1620 } | |
| 1621 return union(error(node.leftOperand), error(node.rightOperand)); | |
| 1622 } | |
| 1623 EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand
) => leftOperand; | |
| 1624 EvaluationResultImpl timesValid(BinaryExpression node, ValidResult leftOperand
) { | |
| 1625 if (!isAnyNum || !leftOperand.isAnyNum) { | |
| 1626 return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); | |
| 1627 } | |
| 1628 if (isSomeInt || leftOperand.isSomeInt) { | |
| 1629 return RESULT_INT; | |
| 1630 } else if (isSomeNum || leftOperand.isSomeNum) { | |
| 1631 return RESULT_NUM; | |
| 1632 } | |
| 1633 Object leftValue = leftOperand.value; | |
| 1634 if (leftValue == null) { | |
| 1635 return error(node.leftOperand); | |
| 1636 } else if (value == null) { | |
| 1637 return error(node.rightOperand); | |
| 1638 } else if (leftValue is int) { | |
| 1639 if (value is int) { | |
| 1640 return valueOf(((leftValue as int)) * (value as int)); | |
| 1641 } else if (value is double) { | |
| 1642 return valueOf3(((leftValue as int)).toDouble() * ((value as double))); | |
| 1643 } | |
| 1644 } else if (leftValue is double) { | |
| 1645 if (value is int) { | |
| 1646 return valueOf3(((leftValue as double)) * ((value as int)).toDouble()); | |
| 1647 } else if (value is double) { | |
| 1648 return valueOf3(((leftValue as double)) * ((value as double))); | |
| 1649 } | |
| 1650 } | |
| 1651 return error(node); | |
| 1652 } | |
| 1653 bool get isNull => identical(this, RESULT_NULL); | |
| 1654 | |
| 1655 /** | |
| 1656 * Return the result of applying boolean conversion to the given value. | |
| 1657 * | |
| 1658 * @param node the node against which errors should be reported | |
| 1659 * @param value the value to be converted to a boolean | |
| 1660 * @return the result of applying boolean conversion to the given value | |
| 1661 */ | |
| 1662 EvaluationResultImpl booleanConversion(ASTNode node, Object value) { | |
| 1663 if (value is bool) { | |
| 1664 if (value as bool) { | |
| 1665 return RESULT_TRUE; | |
| 1666 } else { | |
| 1667 return RESULT_FALSE; | |
| 1668 } | |
| 1669 } | |
| 1670 return error(node); | |
| 1671 } | |
| 1672 ErrorResult error(ASTNode node) => error2(node, CompileTimeErrorCode.INVALID_C
ONSTANT); | |
| 1673 | |
| 1674 /** | |
| 1675 * Return a result object representing an error associated with the given node
. | |
| 1676 * | |
| 1677 * @param node the AST node associated with the error | |
| 1678 * @param code the error code indicating the nature of the error | |
| 1679 * @return a result object representing an error associated with the given nod
e | |
| 1680 */ | |
| 1681 ErrorResult error2(ASTNode node, ErrorCode code) => new ErrorResult.con1(node,
code); | |
| 1682 | |
| 1683 /** | |
| 1684 * Checks if this result has type "bool", with known or unknown value. | |
| 1685 */ | |
| 1686 bool get isAnyBool => isSomeBool || identical(this, RESULT_TRUE) || identical(
this, RESULT_FALSE); | |
| 1687 | |
| 1688 /** | |
| 1689 * Checks if this result has type "int", with known or unknown value. | |
| 1690 */ | |
| 1691 bool get isAnyInt => identical(this, RESULT_INT) || value is int; | |
| 1692 | |
| 1693 /** | |
| 1694 * Checks if this result has one of the types - "bool", "num" or "string"; or
may be `null`. | |
| 1695 */ | |
| 1696 bool get isAnyNullBoolNumString => isNull || isAnyBool || isAnyNum || value is
String; | |
| 1697 | |
| 1698 /** | |
| 1699 * Checks if this result has type "num", with known or unknown value. | |
| 1700 */ | |
| 1701 bool get isAnyNum => isSomeNum || value is num; | |
| 1702 | |
| 1703 /** | |
| 1704 * Checks if this result has type "bool", exact value of which we don't know. | |
| 1705 */ | |
| 1706 bool get isSomeBool => identical(this, RESULT_BOOL); | |
| 1707 | |
| 1708 /** | |
| 1709 * Checks if this result has type "int", exact value of which we don't know. | |
| 1710 */ | |
| 1711 bool get isSomeInt => identical(this, RESULT_INT); | |
| 1712 | |
| 1713 /** | |
| 1714 * Checks if this result has type "num" (or "int"), exact value of which we do
n't know. | |
| 1715 */ | |
| 1716 bool get isSomeNum => identical(this, RESULT_DYNAMIC) || identical(this, RESUL
T_INT) || identical(this, RESULT_NUM); | |
| 1717 double toDouble(int value) => value.toDouble(); | |
| 1718 | |
| 1719 /** | |
| 1720 * Return an error result that is the union of the two given error results. | |
| 1721 * | |
| 1722 * @param firstError the first error to be combined | |
| 1723 * @param secondError the second error to be combined | |
| 1724 * @return an error result that is the union of the two given error results | |
| 1725 */ | |
| 1726 ErrorResult union(ErrorResult firstError, ErrorResult secondError) => new Erro
rResult.con2(firstError, secondError); | |
| 1727 | |
| 1728 /** | |
| 1729 * Return a result object representing the given value. | |
| 1730 * | |
| 1731 * @param value the value to be represented as a result object | |
| 1732 * @return a result object representing the given value | |
| 1733 */ | |
| 1734 ValidResult valueOf(int value) => new ValidResult(value); | |
| 1735 | |
| 1736 /** | |
| 1737 * Return a result object representing the given value. | |
| 1738 * | |
| 1739 * @param value the value to be represented as a result object | |
| 1740 * @return a result object representing the given value | |
| 1741 */ | |
| 1742 ValidResult valueOf2(bool value) => value ? RESULT_TRUE : RESULT_FALSE; | |
| 1743 | |
| 1744 /** | |
| 1745 * Return a result object representing the given value. | |
| 1746 * | |
| 1747 * @param value the value to be represented as a result object | |
| 1748 * @return a result object representing the given value | |
| 1749 */ | |
| 1750 ValidResult valueOf3(double value) => new ValidResult(value); | |
| 1751 | |
| 1752 /** | |
| 1753 * Return a result object representing the given value. | |
| 1754 * | |
| 1755 * @param value the value to be represented as a result object | |
| 1756 * @return a result object representing the given value | |
| 1757 */ | |
| 1758 ValidResult valueOf4(String value) => new ValidResult(value); | |
| 1759 } | |
| OLD | NEW |