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
>>
>>
>

Reply via email to