Chris@13: Constant expression evaluation Chris@13: ============================== Chris@13: Chris@13: Initializers for constants, properties, parameters, etc. have limited support for expressions. For Chris@13: example: Chris@13: Chris@13: ```php Chris@13: evaluateSilently($someExpr); Chris@13: } catch (ConstExprEvaluationException $e) { Chris@13: // Either the expression contains unsupported expression types, Chris@13: // or an error occurred during evaluation Chris@13: } Chris@13: ``` Chris@13: Chris@13: Error handling Chris@13: -------------- Chris@13: Chris@13: The constant evaluator provides two methods, `evaluateDirectly()` and `evaluateSilently()`, which Chris@13: differ in error behavior. `evaluateDirectly()` will evaluate the expression as PHP would, including Chris@13: any generated warnings or Errors. `evaluateSilently()` will instead convert warnings and Errors into Chris@13: a `ConstExprEvaluationException`. For example: Chris@13: Chris@13: ```php Chris@13: evaluateDirectly($expr)); // float(INF) Chris@13: // Warning: Division by zero Chris@13: Chris@13: try { Chris@13: $evaluator->evaluateSilently($expr); Chris@13: } catch (ConstExprEvaluationException $e) { Chris@13: var_dump($e->getPrevious()->getMessage()); // Division by zero Chris@13: } Chris@13: ``` Chris@13: Chris@13: For the purposes of static analysis, you will likely want to use `evaluateSilently()` and leave Chris@13: erroring expressions unevaluated. Chris@13: Chris@13: Unsupported expressions and evaluator fallback Chris@13: ---------------------------------------------- Chris@13: Chris@13: The constant expression evaluator supports all expression types that are permitted in constant Chris@13: expressions, apart from the following: Chris@13: Chris@13: * `Scalar\MagicConst\*` Chris@13: * `Expr\ConstFetch` (only null/false/true are handled) Chris@13: * `Expr\ClassConstFetch` Chris@13: Chris@13: Handling these expression types requires non-local information, such as which global constants are Chris@13: defined. By default, the evaluator will throw a `ConstExprEvaluationException` when it encounters Chris@13: an unsupported expression type. Chris@13: Chris@13: It is possible to override this behavior and support resolution for these expression types by Chris@13: specifying an evaluation fallback function: Chris@13: Chris@13: ```php Chris@13: getType()} cannot be evaluated"); Chris@13: }); Chris@13: Chris@13: try { Chris@13: $evalutator->evaluateSilently($someExpr); Chris@13: } catch (ConstExprEvaluationException $e) { Chris@13: // Handle exception Chris@13: } Chris@13: ``` Chris@13: Chris@13: Implementers are advised to ensure that evaluation of indirect constant references cannot lead to Chris@13: infinite recursion. For example, the following code could lead to infinite recursion if constant Chris@13: lookup is implemented naively. Chris@13: Chris@13: ```php Chris@13: