For now, we don't have any mechanism for annotations or attributes except for doc-comments.
Thanks. Dmitry. On Thu, Feb 5, 2015 at 3:27 PM, Alexander Lisachenko < lisachenko...@gmail.com> wrote: > So, is it possible to use annotations for defining such metadata on > engine-level? This will be a good way to do this and to define custom > handlers via AST hooks, that can be able to patch method definition node > with concrete opcodes. > > 2015-02-05 15:24 GMT+03:00 Alexander Lisachenko <lisachenko...@gmail.com>: > >> Hello, internals! >> >> From my point of view, contracts should not affect execution of source >> code in production env, or can be enabled partially. I have implemented DbC >> paradigm on top of the AOP layer, so each contract can be defined via >> annotation and looks pretty nice, for example : >> >> use PhpDeal\Annotation as Contract; >> >> /** >> * Simple trade account class >> * @Contract\Invariant("$this->balance > 0") >> */ >> class Account implements AccountContract >> { >> >> /** >> * Current balance >> * >> * @var float >> */ >> protected $balance = 0.0; >> >> /** >> * Deposits fixed amount of money to the account >> * >> * @param float $amount >> * >> * @Contract\Verify("$amount>0 && is_numeric($amount)") >> * @Contract\Ensure("$this->balance == $__old->balance+$amount") >> */ >> public function deposit($amount) >> { >> $this->balance += $amount; >> } >> >> /** >> * Returns current balance >> * >> * @Contract\Ensure("$__result == $this->balance") >> * @return float >> */ >> public function getBalance() >> { >> return $this->balance; >> } >> } >> >> All contracts (verify|ensure) are enforced only when DbC is enabled and >> doesn't have an impact on execution for production mode. Moreover, all >> annotations are parsed only once, decorators are generated too, so overhead >> is minimal even for debug mode. Engine takes care to insert appropriate >> before/around checks via an aspect >> https://github.com/lisachenko/php-deal/blob/master/src/PhpDeal/Aspect/ContractCheckerAspect.php >> >> Here is a simple snippet of pointcut definition and advice body: >> >> /** >> * Verifies pre-condition contract for the method >> * >> * @param MethodInvocation $invocation >> * @Before("@annotation(PhpDeal\Annotation\Verify)") >> * >> * @throws ContractViolation >> */ >> public function preConditionContract(MethodInvocation $invocation) >> { >> $object = $invocation->getThis(); >> $args = $this->getMethodArguments($invocation); >> $scope = $invocation->getMethod()->getDeclaringClass()->name; >> >> foreach ($invocation->getMethod()->getAnnotations() as $annotation) { >> if (!$annotation instanceof Contract\Verify) { >> continue; >> } >> >> if (!$this->isContractSatisfied($object, $scope, $args, >> $annotation)) { >> throw new ContractViolation($invocation, $annotation->value); >> }; >> } >> } >> >> >> >> >> >> 2015-02-05 15:13 GMT+03:00 Patrick Schaaf <p...@bof.de>: >> >>> On Thursday 05 February 2015 15:14:04 Dmitry Stogov wrote: >>> > >>> > function foo() >>> > requre(<input-assert-expression>) >>> > ensure(<output-assert-expression>) >>> > { >>> > ... >>> > } >>> > >>> > It would require only one new reserved word "ensure". >>> >>> Regarding syntax.... This could be another place where the irrationally- >>> dreaded declare would make sense: >>> >>> function foo() { >>> declare(pre) { >>> if (whatever...) return false; >>> // arbitrary PHP code >>> } >>> declare(post=$resultvar) { >>> if ($resultvar == XXX) return true; >>> return false; >>> } >>> } >>> >>> This way, no new reserved words are needed at all, and the programmer >>> can give >>> a name to the "variable that holds the result" locally to avoid clashes >>> with >>> anything else in the function. >>> >>> I'm a bit undecided whether returning true/false there to give the >>> verdict, >>> would be the best way. Maybe better would be another use for declare, >>> without >>> a block, to declare that the pre/postcondition failed - giving a nice >>> place to >>> put a suitable message, too. And again without introducing any extra >>> keywords: >>> >>> function foo() { >>> declare(post=$resultvar) { >>> if ($resultvar == XXX) declare(fail="My $resultvar looks fishy"); >>> } >>> } >>> >>> best regards >>> Patrick >>> >>> -- >>> PHP Internals - PHP Runtime Development Mailing List >>> To unsubscribe, visit: http://www.php.net/unsub.php >>> >>> >> >