Re: [PHP-DEV] [VOTE] Userspace operator overloading

2020-03-25 Thread Alexander Lisachenko
Hi, internals!

I want to mention, that all existing internal API of Zend could be
accessible via FFI as of PHP7.4. This gives opportunity to implement
userspace operator overloading as a simple PHP package.

I know, that FFI requires some polishing, but it could become a tool to
create interesting extensions via Z-Engine or similar libraries. Just for
example, I have a repository
https://github.com/lisachenko/native-types which provides an example of
userspace operator-overloading for matrices (see __doOperation method
implementation at
https://github.com/lisachenko/native-types/blob/master/src/Matrix.php#L232-L276
)

Please share you thoughts about this.

Best regards,
Alexander

пн, 23 мар. 2020 г. в 20:58, :

> Hi internals,
>
> I have opened voting on
> https://wiki.php.net/rfc/userspace_operator_overloading, which allows
> users
> to overload operators in their own classes.
>
> Voting closes on 2020-04-06.
>
> Regards,
> Jan Böhmer
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] Re: [VOTE] Object-based token_get_all() alternative

2020-03-25 Thread Alexander Lisachenko
Hello, internals team!

I would like to propose to rename the PhpToken::getAll() method into the
PhpToken::tokenize(string $source) or PhpToken::lex(string $source) to use
a more meaningful verb word.

After renaming, it will sound more natural: $tokenStream =
PhpToken::tokenize($sourceCode)

Best regards,
Alexander


пн, 23 мар. 2020 г. в 19:04, Larry Garfield :

> On Mon, Mar 23, 2020, at 9:07 AM, Nikita Popov wrote:
> > On Fri, Mar 6, 2020 at 10:33 AM Nikita Popov 
> wrote:
> >
> > > Hi internals,
> > >
> > > I've opened voting on https://wiki.php.net/rfc/token_as_object, which
> > > adds a new object-based interface to the tokenizer. Voting closes on
> > > 2020-03-20.
> > >
> >
> > This RFC has been accepted unanimously, with 47 votes in favor.
> >
> > Based on the additional feedback in this thread, I'll also add a
> > __toString() method that returns the value of $token->text, unless anyone
> > has objects to that...
> >
> > Regards,
> > Nikita
>
> As long as __toString() is overridable in subclasses, that seems fine to
> me.
>
> --Larry Garfield
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] [RFC] [DISCUSSION] Scalar Pseudo-type

2017-12-26 Thread Alexander Lisachenko
In some distant future it could be implemented in more natural way with
classes for primitive types and automatic boxing/unboxing for primitive
built-in types:

Php\Type\Object
Php\Type\Scalar
   ⌊ Php\Type\String
   ⌊ Php\Type\Integer
   ⌊ Php\Type\Float
   ⌊ Php\Type\Boolean
Php\Type\Array

And it will be easy to typehint all scalars via common parent class:

public function acceptsScalar(Scalar $scalarValue).

But all scalar objects in this case should be implemented as immutable or
should be passed as copy (like arrays). So, I would vote no for adding
special scalar typehint without mapping it to the common class or
interface, like iterable => Traversable, callable => Closure, etc

Best regards, Alexander

2017-12-26 18:59 GMT+03:00 Andreas Heigl :

> Hey All.
>
> > Am 26.12.2017 um 14:38 schrieb Sebastian Bergmann :
> >
> >> Am 24.12.2017 um 15:34 schrieb Fleshgrinder:
> >> I prepared a PR to add the `scalar` pseudo-type to PHP after the
> >> discussions around adding a `mixed` pseudo-type. I strongly believe that
> >> it makes sense to provide the most common primitive union types with
> >> handy aliases even if we are going to add union types in the future to
> PHP.
> >
> > Thank you, Richard, for working on this.
> >
> > I spent a lot of time this year introducing scalar type declarations into
> > existing code bases. In quite a few cases I was not able to do so because
> > the existing code works with parameters that can be of two or more scalar
> > types. With PHP 7.2, I can only document this outside of the code using
> > @param annotations (until the code has been refactored to work with only
> > one parameter type).
> >
> > With a "scalar" type declaration I would not have to fall back to @param
> > annotations and could express the type in actual syntax.
>
> Just a stupid question from someone that isn't following all the
> discussions here. So forgive me if the question was already asked and
> answered.
>
> What would be wrong with a "composed type hint"? Something like
> int|float|double $numeric. Or array|Traversable $iterator?
>
> It would allow people to add "mixed" typehints without having to introduce
> multiple typehints that combine different scalar typehints. And it could
> even allow typehinting different Objects in one function.
>
> Yes, it allows people to shoot themselfes into their own feet.
>
> And I'd only allow that for parameter types and never ever for return
> types.
>
> But it might be an idea.
>
> Cheers
>
> Andreas
>
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


[PHP-DEV] [Discussion] Deprecate several ReflectionParameter methods

2017-12-26 Thread Alexander Lisachenko
Hi, internals!

I would like to nominate following methods for deprecation in next patch
version of PHP:

   - ReflectionParameter->isArray(),
   - ReflectionParameter->isCallable(),
   - ReflectionParameter->allowsNull(),
   - ReflectionParameter->getClass()

All these methods are covered with ReflectionNamedType API, available for
PHP>=7 via ReflectionParameter->hasType() and
ReflectionParameter->getType().

So, next major version will use ReflectionNamedType API for getting
information about type instead of querying small subset of type information
directly from ReflectionParameter API.

What is your opinion about this? Thanks!

Best regards,
Alexander Lisachenko


Re: [PHP-DEV] PHP's mail servers suck

2017-10-26 Thread Alexander Lisachenko
Hi, internals!

Just quick idea: what about moving from old-school mailing list with
unclear subscription logic and ugly interface to the RFC project on GitHub?
Maybe https://github.com/php/rfc or similar.
There are cases when language developers actively use GitHub for
maintaining RFC-s, label them and review directly in github issues. For
example, https://github.com/rust-lang/rfcs

Organizing internals in this way could give a chance for community to grow,
because everyone knows how to raise an issue on GitHub and how to
contribute to the documentation/RFC.

GitHub also provides flexible way to subscribe to repo/issues/summons.
Maybe it's a good time to move internals to the public open-source system?

Best regards, Alexander

2017-10-26 1:28 GMT+03:00 Tom Samplonius :

>
> > On Oct 25, 2017, at 2:17 PM, Aidan Woods  wrote:
> >
> >> anyways, don't reject mailing-list messages
> >
> > I don't reject the messages, Google rejects the messages because of
> failed
> > DMARC requirements. See support[.]google[.]com/mail/answer/2451690
> >
> > The error occurs when the php mailing list attempts to forward messages
> > from a domain which has a (likey strict) DMARC policy, and sends emails
> as
> > if it was the sender from the domain holding that policy.
> >
> > In any case, despite failed delivery due to the policy being an issue –
> it
> > would be great if I wouldn't be unsubscribed from the mailing list
> because
> > of an error that has nothing to do with me 路‍♂️
>
>   I’m using GSuite for email, and I’ve never received a warning from the
> php.net mail system that mail was bouncing anytime in the past two years,
> nor have I been automatically unsubscribed.
>
>   That said, email is a lot harder than it looks.
>
>
> Tom



2017-10-25 17:30 GMT+03:00 Sara Golemon :

> Quick show of hands: Who's had a "looks like spam" bounce from php.net
> mail servers in the past... lets say the past month.
> Or how about the fact that new users tend to have a very hard time
> even subscribing to this list?
> This isn't directed at any one person because AFAICT, the maintainer
> of those systems is "nobody".
> Is it time to pick someone to actually maintain that pile of mierde?
> Maybe replace the pieces that haven't worked since the 90s?
>
> Fed up with something this basic not working,
> -Sara
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] Decorator classes

2016-12-29 Thread Alexander Lisachenko
2016-12-29 16:12 GMT+03:00 Mathieu Rochette :

> I find that using the decorator pattern is very verbose and maybe
> something could be done about that,
> an article[1] I saw proposed a "decorates" keyword to solves this, here is
> how it might look like in PHP:
>


> * the constructor is optional and default to take the first argument and
> put it in $decorated
> * if the constructor is provided PHP check that $decorated is set and
> implements the decorated interface or class
> * all public methods not overridden are automatically proxied to the
> decorated object
>
> There is at least a few different ways to go about this, the previous
> example was just to give you a preview of what it could be. If there is
> interest I'd like to write an RFC for this :)
>
> What do you think about this ?
>

Hi! I think that language doesn't need any additional keywords for that.
What you describe is pure class inheritance and it's already available in
the language.

To be honest I use class inheritance in Go! AOP to define decorators
because of some nice features:

   1. No overhead for calling non-decorated method (we can wrap only
   required methods)
   2. Only one single instance of class, whereas traditional proxy and
   decorator pattern will use two instances (one for the original instance
   itself and one more instance for proxy/decorator)

What your want can be implemented with the help of one single aspect,
applied to your codebase. Then framework will automatically create
decorators for every required class in your system. For logging decorator
example see my blogpost here:
http://go.aopphp.com/blog/2013/07/21/implementing-logging-aspect-with-doctrine-annotations/


Re: [PHP-DEV] Re: [RFC] Deprecations for PHP 7.2

2016-12-27 Thread Alexander Lisachenko
There was small typo in my previous link to object comparison: new one is
https://3v4l.org/tMokY

2016-12-27 14:33 GMT+03:00 Alexander Lisachenko <lisachenko...@gmail.com>:

> Hi, internals!
>
> I want to propose to deprecate one more weird feature of PHP called
> "comparison of different types" http://php.net/manual/en/
> language.operators.comparison.php#language.operators.comparison.types.
> Here you can check one simple example https://3v4l.org/kCOAf to see why
> it should be deprecated.
>
> It would be nice to deprecate all comparison operators between different
> types and throw an exception later in future version of PHP.
>
> Operators that should be allowed for comparison of different types are the
> following: ==, !=, ===, !==, <>.
> Operators to deprecate for comparison of different types are the
> following: >, <, >=, <=, <=>
>
> I also think about deprecation of string/object/array comparison with
> operators like greater/less, because it's hard to understand results for
> '1000' < '0xabc1' (see https://3v4l.org/o3iLj) or even object comparison
> https://3v4l.org/5At1l
>
> Thanks!
>
> 2016-12-27 9:52 GMT+03:00 Stanislav Malyshev <smalys...@gmail.com>:
>
>> Hi!
>>
>> >> https://wiki.php.net/rfc/deprecations_php_7_2
>>
>> Reading through the list, I find several categories:
>>
>> Completely ok:
>>
>> (unset) - don't see any sane use case anyway
>> gmp_random
>>
>> Can cause breakage but it's ok:
>>
>> $php_errormsg
>> __autoload
>> mbstring.func_overload
>> parse_str() - people can use it in functions, it doesn't have to be
>> globals. But it's cleaner with second arg.
>> $errcontext
>>
>> Don't see a reason to remove:
>>
>> (binary) cast and b"" - yes, they are not currently doing anything. But
>> they don't also hurt anything.
>>
>> High breakage potential:
>>
>> each() - I've seen a lot of code using each. Yes, it's not the best way.
>> A lot of people write code not in absolutely best way but in a way they
>> like to. Argument about list() proposed in RFC makes little sense to me
>> - since problem is with list() and not each() why each() should be
>> deprecated because of it? And I certainly object its removal.
>>
>> create_function() - yes, there are closures now. But there's a lot of
>> code created when there were none, and that code works, and there's no
>> reason to break it. I'd probably be OK with deprecation warning but not
>> with removal.
>>
>> Special case:
>> assert() - if the string arg is a security issue, deprecating it
>> achieves nothing. So I'm not sure I understand the argument for
>> deprecation - if string assert is a problem we probably should make
>> assert() construct instead check if assert is used in eval form, not by
>> argument count?
>>
>> --
>> Stas Malyshev
>> smalys...@gmail.com
>>
>> --
>> PHP Internals - PHP Runtime Development Mailing List
>> To unsubscribe, visit: http://www.php.net/unsub.php
>>
>>
>


Re: [PHP-DEV] Re: [RFC] Deprecations for PHP 7.2

2016-12-27 Thread Alexander Lisachenko
Hi, internals!

I want to propose to deprecate one more weird feature of PHP called
"comparison of different types"
http://php.net/manual/en/language.operators.comparison.php#language.operators.comparison.types.

Here you can check one simple example https://3v4l.org/kCOAf to see why it
should be deprecated.

It would be nice to deprecate all comparison operators between different
types and throw an exception later in future version of PHP.

Operators that should be allowed for comparison of different types are the
following: ==, !=, ===, !==, <>.
Operators to deprecate for comparison of different types are the following:
>, <, >=, <=, <=>

I also think about deprecation of string/object/array comparison with
operators like greater/less, because it's hard to understand results for
'1000' < '0xabc1' (see https://3v4l.org/o3iLj) or even object comparison
https://3v4l.org/5At1l

Thanks!

2016-12-27 9:52 GMT+03:00 Stanislav Malyshev :

> Hi!
>
> >> https://wiki.php.net/rfc/deprecations_php_7_2
>
> Reading through the list, I find several categories:
>
> Completely ok:
>
> (unset) - don't see any sane use case anyway
> gmp_random
>
> Can cause breakage but it's ok:
>
> $php_errormsg
> __autoload
> mbstring.func_overload
> parse_str() - people can use it in functions, it doesn't have to be
> globals. But it's cleaner with second arg.
> $errcontext
>
> Don't see a reason to remove:
>
> (binary) cast and b"" - yes, they are not currently doing anything. But
> they don't also hurt anything.
>
> High breakage potential:
>
> each() - I've seen a lot of code using each. Yes, it's not the best way.
> A lot of people write code not in absolutely best way but in a way they
> like to. Argument about list() proposed in RFC makes little sense to me
> - since problem is with list() and not each() why each() should be
> deprecated because of it? And I certainly object its removal.
>
> create_function() - yes, there are closures now. But there's a lot of
> code created when there were none, and that code works, and there's no
> reason to break it. I'd probably be OK with deprecation warning but not
> with removal.
>
> Special case:
> assert() - if the string arg is a security issue, deprecating it
> achieves nothing. So I'm not sure I understand the argument for
> deprecation - if string assert is a problem we probably should make
> assert() construct instead check if assert is used in eval form, not by
> argument count?
>
> --
> Stas Malyshev
> smalys...@gmail.com
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


[PHP-DEV] Change in method prototyping for interface methods since 7.0.6

2016-12-16 Thread Alexander Lisachenko
Hi, internals!

Today I detected interesting difference in getting prototype methods with
reflection API.
Could you please check this https://3v4l.org/LLebD

Was it intended change?

Thanks!


Re: [PHP-DEV] BC break: ReflectionMethod::invoke() expects parameter1to be object, string given

2016-08-23 Thread Alexander Lisachenko
2016-08-23 18:05 GMT+03:00 Lauri Kenttä :

> Could you do it without reflection, then? I don't think so.
> Thus, I think your "use case" is broken by design.
>


FYI: This use case is used by Go! AOP Framework and AspectMock libraries
that can mock even static methods in the classes, allowing testing legacy
code and singletons. If you are interested in how it works, then you could
look at this example: https://3v4l.org/TbS5V


Re: [PHP-DEV] BC break: ReflectionMethod::invoke() expects parameter1to be object, string given

2016-08-23 Thread Alexander Lisachenko
2016-08-23 16:40 GMT+03:00 Julien Pauli :

> My patch allows that, but I can't find a use case to it.



My use case for that was decorating of static methods with additional
behaviour, so it's possible to cache the result of static methods, etc.
Unfortunately, reflection API doesn't provide me such an ability, so I
decided to switch to the combination of special closure with
forward_static_call_array() and binding it to the desired scope.


2016-08-23 16:40 GMT+03:00 Julien Pauli :

> Try it.


Yes, sure, I will check. However as I say earlier, now I use closure
extraction and scope binding as more natural way to invoke such methods. So
missing scope argument for static methods and ReflectionMethod->invoke() is
a nice thing to have, but not a critical one.


Re: [PHP-DEV] BC break: ReflectionMethod::invoke() expects parameter1to be object, string given

2016-08-23 Thread Alexander Lisachenko
2016-08-23 16:13 GMT+03:00 Julien Pauli :

>
> No, How can this be ?  B extends A , not A extends B ...
> In this case, B'sfoo() will be called , which is the equivalent to
> having a reflectionMethod from B , so useless to me.



Ok, how can I invoke Parent::whoami() with reflection and get exactly
"Child" as an output?

class Parent {
public static function whoami() {
echo static::class;
}
}

class Child extends Parent {
public static function whoami() {
echo "Don't call me now!';
parent::whoami();
}
}


Re: [PHP-DEV] BC break: ReflectionMethod::invoke() expects parameter1to be object, string given

2016-08-23 Thread Alexander Lisachenko
2016-08-23 16:01 GMT+03:00 Julien Pauli :

> This :
>
> class A { public static function foo() { } }
> class B extends A { public static function foo() { }  }
>
> $a = new reflectionMethod('A', 'foo');
> $a->invoke('B');
>


It's perfect way for me.
Just to be sure: in this case we will invoke A::foo() method, but the scope
(static::class) will be 'B', right? If yes, then everything is ok and it
will be compatible with all existing code but will have an additional
meaning for calling methods with children's scope.


Re: [PHP-DEV] BC break: ReflectionMethod::invoke() expects parameter1to be object, string given

2016-08-23 Thread Alexander Lisachenko
2016-08-23 14:51 GMT+03:00 Christoph M. Becker :

> I suggest to deprecate all other types than NULL as first arg for static
> methods, because passing an int, for instance, makes even less sense as
> Rowan has already pointed out elsewhere in this thread.
>


Alternative suggestion (vote for Julien's patch): use first argument as a
string with LSB scope name, see my message from late 2013 year:
http://markmail.org/message/ogeh33jedumgo5lx.

I agree, that all other types don't make any sense. So my suggestion is
following: for dynamic methods it should accept object or null. Null can
mean that we want to unbind the method from the object and maybe call it
like a closure? (just compare this with Closure::bindTo behaviour). For
static methods this could be object (why not - it will be ignored), string
(in this case it will be a scope name if we want to call parent method with
preserving Late Static Binding) or just null (null will be equal to the
string with object class name)

Thoughts?


Re: [PHP-DEV] BC break: ReflectionMethod::invoke() expects parameter 1 to be object, string given

2016-08-22 Thread Alexander Lisachenko
First argument can be a normal string with a valid scope class name for
static methods. This can be useful for calling parent static methods, see
my example.

I think this will be comparable with Closure::call() method and scope
binding.

понедельник, 22 августа 2016 г. пользователь Rowan Collins написал:

> On 22/08/2016 16:40, Christoph M. Becker wrote:
>
>> It is still ignored if it is a valid object, so the current beta's
>>> > behaviour doesn't actually make a lot of sense.
>>>
>> Well, see .  Only as of 7.1.0beta3 ::invoke()
>> matches the behavior of ::invokeArgs().
>>
>
> OK, so that's a further inconsistency. The current version still doesn't
> actually make sense, though. If you want to validate that the correct
> argument is being passed, then the only value allowed should be null.
>
> If so desired, I can revert that commit, but I wouldn't be happy with
>> sticking with a completely unused parameter, which obviously has been
>> and still is misunderstood.
>>
>
> The parameter is still unused, and can be any object. The only sane
> validation would be to check explicitly for null, which is documented as
> the correct argument for both invoke() and invokeArgs().
>
> Regards,
> --
> Rowan Collins
> [IMSoP]
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>


Re: [PHP-DEV] BC break: ReflectionMethod::invoke() expects parameter 1 to be object, string given

2016-08-22 Thread Alexander Lisachenko
Hello, there is one more issue with ReflectionMethod::invoke() for static
methods: it's impossible to call an overridden parent static method and
preserve a scope information:

// https://3v4l.org/ASntq

class foo
{
static function bar()
{
echo self::class, ' vs ', static::class, PHP_EOL;
}

static function bar1()
{
echo self::class, ' vs ', static::class, PHP_EOL;
}
}

class baz extends foo
{
static function bar()
{
echo self::class, ' vs ', static::class, PHP_EOL;
}
}

$r = new ReflectionClass('baz');
$m = $r->getMethod('bar1'); // without overriden method - it's ok, our
static scope is preserved
$m->invoke(null); // foo vs baz

$r = new ReflectionClass('baz');
$m = $r->getMethod('bar'); // with overriden method it's impossible to call
parent static method, no way to specify a scope.
$m->invoke(null); // baz vs baz

// how to statically call the parent static method bar() with scope == baz??

2016-08-22 17:00 GMT+03:00 Levi Morrison :

> On Mon, Aug 22, 2016 at 5:17 AM, Nicolas Grekas <
> nicolas.grekas+...@gmail.com> wrote:
>
> > Hello,
> >
> > now that the BC break on ReflectionType has been reverted, another one
> > remains in ReflectionMethod::invoke():
> >
> > the method doesn't accept a string as first argument anymore, see e.g.:
> >
> > https://3v4l.org/pImmv
> >
> > As you can see, this worked since 5.0 and even in HHVM.
> >
> > It would be great to fix this BC break please.
> >
> > Regards,
> > Nicolas
> >
>
> According to the [documentation][1] it requires an object. If the
> documentation has not been altered recently to make it this way then I'm
> inclined to keep the backward compatibility break. Your example uses a
> static method - you should be passing null and not the name of the class
> (this is also in the documentation).
>
>   [1]: http://php.net/manual/en/reflectionmethod.invoke.php
>


Re: [PHP-DEV] BC break: ReflectionMethod::invoke() expects parameter 1 to be object, string given

2016-08-22 Thread Alexander Lisachenko
If the first argument for invoke() and invokeArgs() for static methods will
be a string with compatible class name for the scope, then it can be used
as a scope modifier (like second argument for Closure::bind($instance,
$scopeClassName))

2016-08-22 17:29 GMT+03:00 Alexander Lisachenko <lisachenko...@gmail.com>:

> Hello, there is one more issue with ReflectionMethod::invoke() for static
> methods: it's impossible to call an overridden parent static method and
> preserve a scope information:
>
> // https://3v4l.org/ASntq
>
> class foo
> {
> static function bar()
> {
> echo self::class, ' vs ', static::class, PHP_EOL;
> }
>
> static function bar1()
> {
> echo self::class, ' vs ', static::class, PHP_EOL;
> }
> }
>
> class baz extends foo
> {
> static function bar()
> {
> echo self::class, ' vs ', static::class, PHP_EOL;
> }
> }
>
> $r = new ReflectionClass('baz');
> $m = $r->getMethod('bar1'); // without overriden method - it's ok, our
> static scope is preserved
> $m->invoke(null); // foo vs baz
>
> $r = new ReflectionClass('baz');
> $m = $r->getMethod('bar'); // with overriden method it's impossible to
> call parent static method, no way to specify a scope.
> $m->invoke(null); // baz vs baz
>
> // how to statically call the parent static method bar() with scope ==
> baz??
>
> 2016-08-22 17:00 GMT+03:00 Levi Morrison <le...@php.net>:
>
>> On Mon, Aug 22, 2016 at 5:17 AM, Nicolas Grekas <
>> nicolas.grekas+...@gmail.com> wrote:
>>
>> > Hello,
>> >
>> > now that the BC break on ReflectionType has been reverted, another one
>> > remains in ReflectionMethod::invoke():
>> >
>> > the method doesn't accept a string as first argument anymore, see e.g.:
>> >
>> > https://3v4l.org/pImmv
>> >
>> > As you can see, this worked since 5.0 and even in HHVM.
>> >
>> > It would be great to fix this BC break please.
>> >
>> > Regards,
>> > Nicolas
>> >
>>
>> According to the [documentation][1] it requires an object. If the
>> documentation has not been altered recently to make it this way then I'm
>> inclined to keep the backward compatibility break. Your example uses a
>> static method - you should be passing null and not the name of the class
>> (this is also in the documentation).
>>
>>   [1]: http://php.net/manual/en/reflectionmethod.invoke.php
>>
>
>


Re: [PHP-DEV] Throwing an Error for require expressions in PHP7.x

2016-06-17 Thread Alexander Lisachenko
Nikita, Dmitry, ping. What do you think, shouldn't we replace all possible
places with Fatal Errors with correct throwing of Error exceptions?  In
this concrete case it's for "require" operator.

>From what I can see Error will give us more control over the file loading
process and make it more atomic, because additional checks
if(file_exists($file) && is_readable($file)) generate extra stat commands,
they are slow and not reliable, because for highload projects, we can be in
the situation where "if" succeeded, but the "require" will fail because our
file was deleted immediately after check.

Code like this:
try {
require $fileName;
} catch (Error $e) {
echo "Oops, maybe deleted? " . $e;
}

is much more reliable than following, by using "include" instead of
"require". This was suggested in https://bugs.php.net/bug.php?id=72089:

if (file_exists($fileName) && is_readable($fileName)) {
@include $fileName; // Silencing errors for the case of race-condition,
etc
}

Pay an attention, that we always need to put the silencing operator here to
prevent warnings, etc. This also hides all internal errors for parsing,
thanks to the PHP. And we can't easily detect the reason why include was
failed. Only possible way is to register error_handler and throw an
instance of ErrorException.

But if require will throw an Error, nothing will changed, because unhandled
Error will produce a Fatal Error, but all modern code will be able to
handle this situation.


Re: [PHP-DEV] Throwing an Error for require expressions in PHP7.x

2016-06-16 Thread Alexander Lisachenko
2016-06-15 22:28 GMT+03:00 Niklas Keller :

> didn't read it was planned for all file functions.



Let's restrict my first suggestion only for "require" expression for now.
So proposal is following:

Rewrite "require" to throw an Error instead of current Fatal Error if some
file can not be loaded. This is fully BC and can be merged into 7.0 and
7.1, because it's impossible to catch a fatal error now. This will be
consistent with handling of eval errors - now we use the ParseError
exception instead of fatal errors.

In my opinion, all fatal errors should be replaced with exception throwing
(if possible), because it's more developer-friendly and allow us to handle
failures gracefully, invoking finally, destructors, etc.


[PHP-DEV] Throwing an Error for require expressions in PHP7.x

2016-06-15 Thread Alexander Lisachenko
Hi, internals!

For PHP7 we have pretty errors for almost everything, even eval can throw a
ParseError exception, but not for the require expression, because it's
still producing an uncatchable fatal errors:

try {
require('no.php');
} catch (Throwable $e) {
echo 'Catch!';
} finally {
echo 'Finally?';
}
// Warning: require(no.php): failed to open stream: No such file or
directory
// Fatal error: require(): Failed opening required 'no.php'

See https://3v4l.org/sQeAQ for live demo. What are the reasons not to throw
Error here? Looks like an oversight for me.

Can we also add FileNotFoundException and use it for all file functions to
avoid silencing with "@" operator? Then require expression can throw an
Error with nested FileNotFoundException.

Thoughts?


Re: [PHP-DEV] Attributes/Annotations Case Study: Drupal

2016-05-05 Thread Alexander Lisachenko
Hello, internals!


2016-05-05 9:48 GMT+03:00 Stanislav Malyshev :

> Maybe that's what we want to have here - freedom for everybody to invent
> their own languages - but I fear the danger of fragmentation here and
> also people implementing tons of slightly different incompatible parsers
> for ASTs that are generated. We'd have Drupal attributes and Symphony
> attributes and Doctrine attributes and Zend attributes and so on, and
> each of them would have different semantics. Not sure this would be
> good. But maybe it avoids arguing about the syntax now.
>

AST for attributes is a nice thing for abstracting from the concrete
details about how attribute is handling by the concrete implementation. I
can see a lot of common with class autoloading - earlier there were a lot
of custom loaders, thanks to spl_autoload_register() that defines a stack
of callbacks responsible for loading classes by their names. And everyone
uses custom class loader, but later PSR-0 and PSR-4 were described and
adopted in composer, so now we have one general tool for that. What if we
select the same direction with the stack of callback?

How it should work: PHP engine stores all attributes in the plain AST
without any transformations. This data should be accessible via
ReflectionXXX->getAttributes(ReflectionAttribute::RETURN_AST). After that
userland library can register a hook as attribute loader: e.g
ReflectionAttribute::registerProcessor(SomeHandler::class, $isPrepend =
true) or spl_attribute_handler_register(SomeProcessor::class, $isPrepend =
true)

Each processor is a class with two methods:

interface AttributeProcessorInterface {
public function supports(Php\Ast\Node $attributeNode) : boolean;
/** @return mixed */
public function process(Php\Ast\Node $attributeNode);
}

After that if we call
ReflectionXXX->getAttributes(ReflectionAttribute::RETURN_VALUE) PHP engine
will call each processor and asks it if it supports this AST node. If
processor supports this node, then engine call it's process($attributeNode)
method, returning the result as a result, otherwise looks for another
processor. If no processors can handle this AST then PHP can throw an
exception about with information about missing processors for attributes.

I think this way can give a good start point with possibility to
standardize handling of attributes in the future. From the PHP engine side,
all attributes are AST nodes that can be processed later on the userland
side.


Re: [PHP-DEV] [RFC][Discussion] Parser extension API

2016-04-26 Thread Alexander Lisachenko
2016-04-26 11:15 GMT+03:00 Nikita Popov :

> As an update here, I plan to create an RFC for bundling the php-ast
> extension (maybe with minor modifications) with php-src. This was planned
> for 7.1 anyway, and with the annotations RFC under discussion, this seems
> like a good time.
>
...
>
I'll try to post an RFC for review this week.
>

Hello, Nikita!

It's a great news! Having this stuff in the 7.1 core is awesome!

But I have several petitions for this API:
1) Could it avoid using of raw functions for parsing API, like
ast\parse_file or ast\parse_code
2) Could you please put all the parsing stuff into the `Parser` class and
put it into the `Php\` namespace, as well with node classes?


Re: [PHP-DEV] [RFC][Discussion] Parser extension API

2016-04-26 Thread Alexander Lisachenko
Hello, internals!

I'd like to bring this topic to the discussion again, because now we have a
shiny PHP7 engine and keep moving. PHP grammar becomes more complex and
internal AST representation isn't available for the userland developers, so
all static analysis tools suffering from the lack of native AST API for
that. Only possible way for that is to perform tokenization of source code
and then manually reconstruct an AST (thanks to the PHP-Parser and Nikita
for doing this job for us, developers)

Several days ago, Dmitry published a RFC for native attributes, which can
be a great tool for building more complex stuff on top of this metadata.
However, all attribute expressions will be stored as an AST nodes, so we
need an AST API again to analyse, parse or compile AST back into the source
code for evaling, etc.

It would be nice to push php-ast extension (or similar one) into the core,
providing an API via static class, for example "Php\Parser".

2015-03-03 19:12 GMT+03:00 Leigh <lei...@gmail.com>:

> On 3 March 2015 at 11:56, Alexander Lisachenko <lisachenko...@gmail.com>
> wrote:
> > Good morning!
> >
> > I have cleaned https://wiki.php.net/rfc/parser-extension-api and
> restricted
> > it's scope only to the parsing API. Extension API can be implemented
> later
>
> +1
>
> > on top of
> >
> https://github.com/php/php-src/commit/1010b0ea4f4b9f96ae744f04c1191ac228580e48
> > and current implementation, because it requires a lot of discussion and
> can
> > not be implemented right now.
>
> I had no idea that zend_ast_process was such a recent addition, and
> part of your proposal. I've actually started using it already
> completely independently in one of my extensions!
>
> > 1. Should each node type be represented as personal class?
> > There are two possible ways: single node class for everything (current
> > proposal) and separate class for every node kind. I have made a quick
> > research of AST API in several languages and noticed, that most of them
> > generates AST class nodes automatically. E.g. UnaryOperationNode,
> > StatementNode... This way is cool, but it requires a lot of classes to be
> > loaded and available as API. Pros: SRP of each node class, AST validators
> > (can be described with XML and DTD), more clear code analysis (checks
> with
> > $node instaceof StatementNode), typehints for concrete nodes for
> visitors.
> > However, PHP is dynamic language and we can use only one class for
> > everything, adjusting `kind` property for each node. Pros: single class,
> > easier to maintain and to use. Cons: bad UX (how to validate nodes, how
> to
> > determine number of available children, how to check is node using flags
> or
> > not, etc)
>
> I think we need to at least represent all of the current node structures.
>
> A common base class, and then classes to represent lists, zvals and
> decls that extend from this base.
>
> > 2. Where metadata should be stored (flags, names of kind nodes, relation
> > between node types)? This information will be needed later for validation
> > of AST
> >
> > Nikita have some thoughts for the future :) So he asked about the storage
> > of metadata to validate an AST and to perform some analysis on it.
> Metadata
> > should include the following: name of each node kind (this can be just a
> > class name of node or constants in the class), node restrictions (which
> > kind of node types can be used as children for concrete node; number of
> > children nodes), node flag names (it's PUBLIC, PROTECTED, PRIVATE, etc)
>
> Thinking for the future is fine, but do we need this metadata for the
> current proposal? Is the AST returned by the parser in a read-only
> state, or can users create their own nodes + children and get a pretty
> printed output? If it's the latter then we obviously need to know the
> restrictions.
>
> I think we need a mechanism that keeps names/numbers in sync
> automatically, maybe we can use some macros to automatically generate
> enums and userland facing details at the same time, so we don't have
> to keep several places in sync if/when new AST nodes are added.
>


Re: [PHP-DEV] Forbid binding methods to incompatible $this

2016-03-30 Thread Alexander Lisachenko
Hello, internals!

Go! AOP was used closure rebinding to an incompatible context only for one
minor specific feature, called privileged advices, where method was
executing in the context of target class. But all main closure binding in
the framework core work only with compatible contexts, so everything is ok
with PHP7 now.

So, this new patch is ok for me. Anyway, if I need this functionality
again, I can convert methods to the closures via AST transformation of
classes.

2016-03-30 14:02 GMT+03:00 Nikita Popov :

> On Wed, Mar 30, 2016 at 11:34 AM, Dmitry Stogov  wrote:
>
> > I agree, this ability is a dirty and annoying hack, but I'm sure, some
> > people use it.
> >
> > Tony, you don't use this in the new runkit replacement? :)
> >
> > Thanks. Dmitry.
> >
>
> Is this referring to https://github.com/badoo/soft-mocks? If so, searching
> the codebase for getClosure gives no results, so it shouldn't be affected.
>
> I know that the Go! AOP framework used to do some odd things with closure
> binding on methods. However their use case was *already* completely broken
> by the limitations we added in 7.0 and the feature was removed.
>
> Nikita
>


Re: [PHP-DEV] Re: RFC Operator Overloading in Userspace

2016-01-05 Thread Alexander Lisachenko
2016-01-05 2:04 GMT+03:00 Andrea Faulds :

> I agree that we could do something with interfaces. I would like to point
> out that we actually already have an example of this, in the form of the
> \ArrayAccess interface, which requires you to implement all the different
> indexing operations at once. Unfortunately, though, \ArrayAccess doesn't
> give us a precedent for dealing with the $this issue (in `$a + $b`, who
> gets called, how do we handle differing types, etc?), but it's a start.
>


Hi, Andrea and internals team!

Interface is a good way to implement new functionality for classes, but
operator overloading is language feature itself, so from my point of view,
it will be better to put this functionality into the magic method.
Personally, I don't like hundreds of __add, __mul, __etc methods, because
this will be ugly and will require addition of new methods when new
operators are included (eg __pow).

I want to suggest to add only one single method:

public function __operator(int $operatorKind, ...$operatorArgs);

This method will be called for every operator and class can check the
$operatorKind variable with simple check: if (Php\Operator::OP_DIVISION ===
$operatorKind) return $operatorArgs[0]->value / $operatorArgs[1]->value;
New values for operator type enumeration can be added later into new
versions of PHP easily.


Re: [PHP-DEV] Immutable modifier

2015-11-17 Thread Alexander Lisachenko
Hello, internals!

We discussed this topic early, see this thread:
http://www.serverphorums.com/read.php?7,1123371,1124223 for any additional
thoughts and ideas. I want to attach a link to the Java draft of partial
immutability of objects:
http://cr.openjdk.java.net/~jrose/values/values-0.html, it's pretty
interesting and can be applied for PHP too.

I very like the whole idea of having native immutability for objects and
see a many cases where it can be applied.

I'm thinking about immutability for objects as passing variables as a copy
by value, not by reference. Const keyword can be used for that:

class Foo {
 public static function bar(const Baz $object) {  // Require an
instance of Baz to be passed as a copy, not a reference
 $object->test = '12345'; // Will throw an exception, because for
immutable object property fetching for writing is not allowed
 $object = 12345; // Will throw an exception, immutable variable
can not modified

 $myObject = $object; // Create our local copy of immutable object,
this will be a full copy (clone)
 $myObject->test = '456'; // OK
 echo $myObject->test, ' original is ', $object->test; // Will
output: '456 original is foo'
 }
}

$obj = new Baz; // Our local instance, #1
$obj->test = 'foo';
Foo::bar($obj); // Method requires immutability, so a new copy of $obj will
be created before passing value to the method

echo $obj->test; // Outputs 'foo'

Here, an original object will be preserved in any case, because a copy will
be used (probably, via cloning) and engine will check some restrictions to
keep variable immutability.

Some more code examples:

function foo() {
const $bar = new stdClass; // We use const keyword with variable name
to declare it immutable
$bar = 1; // Will throw an exception, because $bar is immutable const
variable
$bar->test = 123; // Will throw an exception, because for immutable
variable which is object property fetch for writing is not allowed

const $immutableArray = [1, 2, 3];
$immutableArray[] = 4; // Immutable array can not be modified, only
read operation is supported

$mutableArray = $immutableArray; // If we make a copy of variable
without const, it can be changed later via Copy-on-Write
$mutableArray[] = 5; // OK, local copy is used
}

Function or methods can declare a return result to be immutable by adding a
"const" keyword into the declaration:

const function foo() : Baz // declare our function to return an immutable
copy of object
{
$object = new Baz;
$object->test = 456;
return $object;
}

$value = foo(); // Will throw an exception, immutable return result from
the function can be assigned only to the immutable variable
const $immutableValue = foo(); // OK, immutable result is stored in the
immutable variable

ReflectionParameter, ReflectionFunctionAbstract can have an additional
methods: ReflectionParameter->isImmutable() or
RelectionParameter->isConst();
ReflectionFunctionAbstract->returnsImmutableValue()



2015-11-17 10:18 GMT+03:00 Chris Riley :

> On Tue, 17 Nov 2015, 02:07 Andrea Faulds  wrote:
>
> Hi,
>
> Chris Riley wrote:
> >
> > There has been a lot of interest recently (eg psr-7) in immutable data.
> I'm
> > considering putting an RFC together to add language support for
> immutables:
> >
>
> I wonder if immutable classes are really the right way to go. Immutable
> reference types with manual copying are somewhat alien to PHP: instead,
> the language has used copy-on-write mutable value types for arrays and
> strings, and prior to PHP 5, objects.
>
> Copy-on-write value types have all the benefits immutable types do. They
> can't be mutated at a distance unless you make a reference to them,
> trees made of them can be compared for equality with just ===, etc.
>
> But they also have benefits that immutable types lack. They're easier to
> work with, because you can directly mutate them like everyone's used to
> doing: no messing around with withFooBar() and withoutFooBar(), you just
> set foobar or remove it directly. And PHP handles the duplication of
> objects for you implicitly, so there's far less code to write.
>
> Unfortunately, PHP 5 got rid of PHP 4's value type objects and replaced
> them with reference type objects. But we could always introduce a way to
> get value type objects again. How about a `struct` keyword? It would be
> equivalent to `class`, but produce a value type rather than a reference
> type.
>
> Any thoughts?
>
> Thanks.
> --
> Andrea Faulds
> http:// ajf.me/ 
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http:// www.php.net
> / unsub.php
> 
>
>
> My main motivation for this was for event objects when doing event sourcing
> - they are by definition unchangeable after creation. That said,
> 

Re: [PHP-DEV] [Question] Variadic method signature compatibility between 5.6 and 7.0

2015-11-02 Thread Alexander Lisachenko
2015-11-02 12:22 GMT+03:00 Rowan Collins :

> Should they? func_get_args() can be used to simulate any function
> signature, so you could equally say that the following are "compatible":



Hello! Thank you for the answer.
However, question is not about func_get_args() at all, it can be removed to
simplify an example. However, I still have a doubts that these two
signatures are not compatible.

First definition declares exactly one single parameter, which can be absent
during the method call, so I can even write

public static function test() {}

Second definition defines zero or more arguments, so it can be also
described by the same signature:

public static function test() {}

Signature with variadic args will be incompatible if the first definition
requires additional arguments before optional and second signature doesn't
respect this, see https://3v4l.org/5Fsou (this behaviour is correct and
warnings are expected).

But if the number of required parameters are matching, then whole signature
should be matching. PHP5.6 with HHVM prove this fact, see:
https://3v4l.org/YCmPS, and PHP7.0 probably doesn't play well.

If you think, that the new logic in PHP7.0 is correct, then it should be
nice to have a small notice in BC change with PHP5.6 logic, somewhere in
http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.other.func-parameters
.


[PHP-DEV] [Question] Variadic method signature compatibility between 5.6 and 7.0

2015-11-01 Thread Alexander Lisachenko
Hello, internals!

I have a question about changed behavior in 7.0 for matching signature of
variadic method.

Here is an example of code:

class Foo {
public static function test($bar = null) {
var_dump(func_get_args());
}
}

class Baz extends Foo {
public static function test(...$args) {
parent::test(...$args);
}
}

Baz::test();
Baz::test('hello');

For 5.6 this code works normally, but in 7.0 it produces a warning about
signature: "Warning: Declaration of Baz::test(...$args) should be
compatible with Foo::test($bar = NULL)"

See https://3v4l.org/so6P2

>From userland point of view, these signatures should be compatible, so I
decided to check this behavior, was it intended or not.

Thanks!


Re: [PHP-DEV] Re: Forbid rebinding scope of closures created by ReflectionFunctionAbstract::getClosure()

2015-10-23 Thread Alexander Lisachenko
2015-10-22 18:48 GMT+03:00 Julien Pauli :

> This is very tricky use case IMO.
>
> We should absolutely focus on stability, and if we can't find a way to
> make things safe, we forbid them
> for the stability sake. If there are no way to have stable things,
> well, that's pitty but it's like that.
>
> We can't allow PHP to release with a known crashing behavior.
>
> Perhaps we'll find new ways to do things in 7.1 or next 8.0.
>


Good morning! Thank you, Julien, for paying an attention to my message and
pointing to the things that are more important. I'm absolutely agree with
you that the stability of the core is priority task for now, so it will be
better to keep php7.0 core as stable as possible.

Of course, this patch introduces some BC breaks, because now code that
accepts \Closure instance should be able to check, if this instance of
closure from ReflectionFunction or not to decide about possibility of
binding. Technically they should be equal.

Today I was able to test my code with RC5 and things aren't so bad, all
main features working, except minor ones ) All dynamic methods can be
called with closures, because I only need instance rebinding for closure,
not the scope, because it's already passed as argument for
getClosure($this). Simplified example https://3v4l.org/WRuZ6. For static
methods, keeping LSB with closures is tricky, but it works via
forward_static_call_array and putting it into the closure, which can be
easily binded to the required scope: https://3v4l.org/kLN0E

So, it's not a big deal for me anymore, all other things are tricky and
aren't used very often. Thanks!


Re: [PHP-DEV] Re: Forbid rebinding scope of closures created by ReflectionFunctionAbstract::getClosure()

2015-10-19 Thread Alexander Lisachenko
2015-10-19 12:19 GMT+03:00 Nikita Popov :

> This change is primarily targeting userland methods, so your use-case is
> exactly the one this is supposed to prevent. Note that you can still use
> ->bindTo($object). The only thing you cannot do is ->bindTo($object,
> get_class($object)).



It's very pity ( It was a very interesting feature that gives a birth for
userland AOP, without it part of framework functionality *will be lost*.
>From the list of attached bugs I can see that all weird stuff happens only
with internal classes/functions/methods. I never have seen a segfaults in
my code that heavily uses closure rebinding with userland methods/classes
and expect it to work in all future versions of PHP, starting from >=5.4.

I don't know PHP engine well, but this feature with scope rebinding for
methods allows some interesting patterns, like "Spy", "Field initializer",
"Lazy proxy initializer", etc. We just take one method and bind it to
another scope to perform an additional logic if needed.

Maybe, apply your patch only to internal functions (restrict them to have
$this inside) and simple functions? This will cover most bugs, but won't
break an exisitng code.


Re: [PHP-DEV] Re: Forbid rebinding scope of closures created by ReflectionFunctionAbstract::getClosure()

2015-10-19 Thread Alexander Lisachenko
Hello, internals!

Just noticed this thread and want to clarify some things with getClosure()
method. If i understood correctly, ReflectionFunctionAbstract::getClosure()
should return non-rebindable closure ONLY for internal functions, but for
userland functions binding should be still possible, right?

E.g.

class Foo {private $a=1;}

function test() {
var_dump($this);
}
$closure = (new \ReflectionFunction('test'))->getClosure();
$object = new Foo;
$closure = $closure->bindTo($object, get_class($object));
$closure();

(unfortunately, it's broken: https://3v4l.org/YeDBj#v700rc5)

I know, that binding functions to objects is tricky, but this can be useful
for utility classes. But if you insist on this, ok, it's very rare case,
just one single example.

What is more important for me is ability to work with methods as closures.
So my main concern is about restrictions of ReflectionMethod->getClosure()
and rebinding.

See this example:

class Foo {private $a=1;}

class Bar {
function test() {
var_dump($this);
}
}
$closure = (new \ReflectionMethod('Bar','test'))->getClosure(new Bar);
$object = new Foo;
$closure = $closure->bindTo($object, get_class($object));
$closure();

This kind of rebinding is heavily used by Go! Aspect-Oriented Framework and
now it will be broken (see https://3v4l.org/cZtbI#v700rc5). I think there
will be some more frameworks/libraries that use reflection and closure
rebinding via reflections. So this introduced patch for RC5 is definitely a
BC break for existing code.
Could you please provide a workaround or alternative ways to keep it
working? Maybe, restrict rebinding only for internal objects/methods will
be enough? Or only for ReflectionFunctionAbstract->getClosure(), but not
for ReflectionMethod->getClosure()

Thanks!

2015-10-13 10:27 GMT+03:00 Anatol Belski :

> Hi,
>
> > -Original Message-
> > From: Xinchen Hui [mailto:larue...@php.net]
> > Sent: Tuesday, October 13, 2015 4:23 AM
> > To: Anatol Belski 
> > Cc: Nikita Popov ; Dmitry Stogov  >;
> > PHP internals 
> > Subject: Re: [PHP-DEV] Re: Forbid rebinding scope of closures created by
> > ReflectionFunctionAbstract::getClosure()
> >
> > Hey:
> >
> > On Tue, Oct 13, 2015 at 6:12 AM, Anatol Belski 
> > wrote:
> >
> > >
> > >
> > > > -Original Message-
> > > > From: Nikita Popov [mailto:nikita@gmail.com]
> > > > Sent: Monday, October 12, 2015 10:33 PM
> > > > To: Anatol Belski 
> > > > Cc: Dmitry Stogov ; PHP internals <
> > > internals@lists.php.net>
> > > > Subject: Re: [PHP-DEV] Re: Forbid rebinding scope of closures
> > > > created by
> > > > ReflectionFunctionAbstract::getClosure()
> > > >
> > > > On Mon, Oct 12, 2015 at 10:22 PM, Anatol Belski
> > > > 
> > > > wrote:
> > > >
> > > > > Hi,
> > > > >
> > > > > > -Original Message-
> > > > > > From: Nikita Popov [mailto:nikita@gmail.com]
> > > > > > Sent: Monday, October 12, 2015 8:57 PM
> > > > > > To: Dmitry Stogov 
> > > > > > Cc: PHP internals ; Andrea Faulds
> > > > > > ;
> > > > > Stas
> > > > > > Malyshev ; Bob Weinand
> > ;
> > > > > > Anatol Belski 
> > > > > > Subject: [PHP-DEV] Re: Forbid rebinding scope of closures
> > > > > > created by
> > > > > > ReflectionFunctionAbstract::getClosure()
> > > > > >
> > > > > > > It would be great, if we stop any commits into PHP-7.0 except
> > > > > > > for
> > > > > > critical fixes now
> > > > > >
> > > > > > Maybe keep PHP-7.0 open (or as open as release branches usually
> > > > > > are),
> > > > > but from
> > > > > > now on only cherry-pick critical fixes into PHP-7.0.0 (instead
> > > > > > of merging everything)?
> > > > > >
> > > > > I commit myself to Dmitry's words. What matters today and
> > > > > especially after
> > > > > RC5 is the stability. Today we should invest into testing and bug
> > > > > fixes more than into improvements (aka fixes to something that is
> > > > > not broken). It really matters for the quality of the final.
> > > > > That's the message to convey probably.
> > > > >
> > > >
> > > > To rephrase my question: Should we treat PHP-7.0 the same way we
> > > > treat
> > > > PHP-5.6 and other release branches (i.e. all kinds of bug fixes are
> > > okay, even if
> > > > it's just improving a test or fixing some inconsequential behavior),
> > > > or
> > > do you
> > > > want to limit the PHP-7.0 branch to actually critical fixes now?
> > > > From
> > > what you
> > > > say, I assume the former rather than the latter?
> > > >
> > > Talking about "critical" I meant usual definitions as something that
> > > causes memory corruptions, data loss, big functional impact, security
> > > flaws, etc.
> > >
> > agree, bugs
> >
> > >
> > > The tricky point 

Re: [PHP-DEV] Exposing object handles to userland

2015-08-03 Thread Alexander Lisachenko
Hello, internals!

I like the idea to assign a custom identifier to the object, but why this
should be only in the core? Java has a method 'hashCode' which can be used
to return an unique identifier for specific object. So, my suggestion is to
add 'Hashable' interface for that into the PHP.

Then, each developer can use a default implementation which will return
spl_object_id/spl_object_hash/whatever or implement this interface to
control the unique identifier of current object:

class Test implements Hashable
{
private static $objectCounter = 100500;
private $identifier = null;
public function __construct()
{
$this-identifier = self::$objectCounter++;
}

public function hashCode()
{
return __CLASS__ . ':'. $this-identifier;
}
}

echo spl_object_hash(new Test); // Will return 'Test:100500'

This solution is more flexible and can give a freedom for implementations.
What do you think about this random thought?

Thanks.

2015-08-03 10:20 GMT+03:00 Nicolas Grekas nicolas.grekas+...@gmail.com:

 2015-08-02 20:03 GMT+02:00 Rowan Collins rowan.coll...@gmail.com:

  On 02/08/2015 18:41, Bob Weinand wrote:
 
  Some suspicious use of spl_object_hash() out there...
  
 
  
 
 https://github.com/symfony/symfony/blob/master/src/Symfony/Component/VarDumper/Cloner/VarCloner.php
 
  
  Not sure what this one does... but calculations with spl_object_hash()
  look very suspicious.
 
  Actually, it's doing the right thing… calculating the value the object
 id
  is xor'ed with (as we know that consecutively defined objects have
  consecutive ids).
  It's relying on the implementation of spl_object_hash() and will even
  continue to work when we remove that part of randomness as that value
 it's
  xor'ed with is then nothing else than 0.
 
 
  The right thing for what purpose? Why does it need that ID, rather than
  the value that spl_object_hash() gave in the first place? Just to be
  prettier to the user?
 


 For the purpose of providing an id that humans can read and compare, to
 easily spot if two objects are identical or not. Try comparing two
 spl_object_hashes and you'll understand the need...

 The id as displayed by e.g. var_dump is not an implementation detail that
 leaks through it.
 It's really an important feature of the output.

 I learned that while implementing VarDumper (see link above), by user
 requests.

 Regards,
 Nicolas



Re: [PHP-DEV] Exposing object handles to userland

2015-08-03 Thread Alexander Lisachenko
2015-08-03 16:10 GMT+03:00 Etienne Kneuss col...@php.net:

 As for PHP, It seems like what people actually want is a unique identifier
 for objects (for the lifetime of the request), but they compromise and use
 the handle instead as it is available without userland counter.


Probable, there is no actual need for that (to have a unique identifier for
each object). Reasons are following: unique identifier is not reliable
(depends on the object creation sequence, can be reused later), not
predictable (it's not possible to say that one object is the same with
another one, which was present in a previous request).

Only the case I can see is to store multiple objects in the one list for
several reasons (e.g. mediators, etc). But it isn't a task for the core to
generate a unique identifer for each object, it's a task for developer to
implement this, otherwise it's still unclear, how to compare different
objects (for example, during comparison of unserialized objects and an
existing one, which can have a different internal object ID).

Implementation of Hashable interface can give an answer to that: two
objects can be considered equal if they have a same hash code, for example,
sha1(json_encode(get_object_vars($this)));


Re: [PHP-DEV] PHP-FPM: How to clear the realpath cache on deployment?

2015-06-23 Thread Alexander Lisachenko
Hello, internals!

I remember the crazy code for invalidating the opcache/realpath entries
from CLI.

Logic was the following: tool asks for the server name with php-fpm to
connect to via ssh connection, then it prepares a small PHP-file and
uploads it to the temp directory on this server and then connects directly
to the php-fpm socket on this server via FCGI protocol (implemented in PHP)
to issue an request to this temporary file. So, it's possible to access all
shared variables/states in this php-fpm instance.

After that it's possible to execute a command in the context of server.
This can be used for invalidating the realapth/opcode cache. Hope, that
this information can be useful for you )

Thanks

2015-06-22 23:27 GMT+03:00 Ferenc Kovacs tyr...@gmail.com:

 On Mon, Jun 22, 2015 at 9:26 PM, Sebastian Bergmann sebast...@php.net
 wrote:

  On 06/19/2015 05:46 PM, Rasmus Lerdorf wrote:
   I think this is a symptom of doing deploys incorrectly.
 
   You are right, of course. Thank you for pointing out this layer 8
   problem :-) No clue why I did it different (read: stupid) for a
   private project when I know better. Oh, well.
 
  --
  PHP Internals - PHP Runtime Development Mailing List
  To unsubscribe, visit: http://www.php.net/unsub.php
 
 
 another alternative is using absolute paths everywhere:

 http://grokbase.com/p/php/php-internals/133qxh5ndm/php-dev-continuous-integration-atomic-deploys-and-php-5-5

 --
 Ferenc Kovács
 @Tyr43l - http://tyrael.hu



Re: [PHP-DEV] [Q] Does PHP have a negative cache for file stat operations?

2015-03-20 Thread Alexander Lisachenko
I want to mention
http://php.net/manual/en/opcache.configuration.php#ini.opcache.enable-file-override
option, that can cache positive checks information between subsequent
requests.

Thanks!

2015-03-20 9:13 GMT+03:00 Stanislav Malyshev smalys...@gmail.com:

 Hi!

  We're doing some performance work in WinCache, and we're finding that
  some frameworks are...uh...enthusiastically using file_exists(),
  is_file() and is_dir() functions on files/directories that don't
  exist.  Every. Single. Pageload.
 
  Does the PHP stat cache include negative cache entries?  If not, why
  not?

 Negative cache is tricky. Most frequent patterns look like this:

 1. if(file_exists(blah)) { do stuff }

 2. if(!file_exists(blah)) { throw new Exception(no blah!); }
 do stuff

 3. if(!file_exists(blah)) { create(blah); }
 do stuff

 Caching negative even short term would subtly break case 3, in that it
 would force creation of the file every time, thus killing any benefit
 from any caching (usually file creation is much more expensive process).
 Long term caching would also be big trouble with case 2. Unless there's
 a way to reset the cache and the app is very careful to do it - but file
 can be created by external means and also case 2 would be harder to fix
 without losing the benefits of caching.

 So one may ask, why case 1 is not a problem? Usually it's because if the
 file is there, apps rarely delete them by themselves, or at least adding
 new files is much more frequent operation than deleting existing ones
 that are used by the app.
 --
 Stas Malyshev
 smalys...@gmail.com

 --
 PHP Internals - PHP Runtime Development Mailing List
 To unsubscribe, visit: http://www.php.net/unsub.php




Re: [PHP-DEV] Use behavior thoughts

2015-03-06 Thread Alexander Lisachenko
Hello!

2015-03-05 22:40 GMT+03:00 Anthony Ferrara ircmax...@gmail.com:

 This requires use to immediately follow namespace declarations:

 namespace Foo {
 use Bar; //valid
 }
 namespace Bar {
 use Foo; //valid, second namespace in file
 }
 namespace Baz {
 echo Hi!;
 use Foo; // Invalid
 }

 This did break approximately 30 internal tests, but they were all
 testing this specific code path (or bugs related to it).


I like this way, because it's more logical and readable. There aren't
unpredictable effects and misunderstanding with interpretation of source
code.


Re: [PHP-DEV] [RFC][Discussion] Parser extension API

2015-03-03 Thread Alexander Lisachenko
Good morning!

I have cleaned https://wiki.php.net/rfc/parser-extension-api and restricted
it's scope only to the parsing API. Extension API can be implemented later
on top of
https://github.com/php/php-src/commit/1010b0ea4f4b9f96ae744f04c1191ac228580e48
and current implementation, because it requires a lot of discussion and can
not be implemented right now.

I want to move this RFC to the vote phase soon to decide if it will be
included into PHP7.0 or not.

So let's discuss open questions before moving it to the vote phase (from SO
chat)

1. Should each node type be represented as personal class?
There are two possible ways: single node class for everything (current
proposal) and separate class for every node kind. I have made a quick
research of AST API in several languages and noticed, that most of them
generates AST class nodes automatically. E.g. UnaryOperationNode,
StatementNode... This way is cool, but it requires a lot of classes to be
loaded and available as API. Pros: SRP of each node class, AST validators
(can be described with XML and DTD), more clear code analysis (checks with
$node instaceof StatementNode), typehints for concrete nodes for visitors.
However, PHP is dynamic language and we can use only one class for
everything, adjusting `kind` property for each node. Pros: single class,
easier to maintain and to use. Cons: bad UX (how to validate nodes, how to
determine number of available children, how to check is node using flags or
not, etc)


2. Where metadata should be stored (flags, names of kind nodes, relation
between node types)? This information will be needed later for validation
of AST

Nikita have some thoughts for the future :) So he asked about the storage
of metadata to validate an AST and to perform some analysis on it. Metadata
should include the following: name of each node kind (this can be just a
class name of node or constants in the class), node restrictions (which
kind of node types can be used as children for concrete node; number of
children nodes), node flag names (it's PUBLIC, PROTECTED, PRIVATE, etc)

2015-02-19 10:22 GMT+03:00 Dmitry Stogov dmi...@zend.com:



 On Thu, Feb 19, 2015 at 8:42 AM, Sara Golemon poll...@php.net wrote:

 On Wed, Feb 18, 2015 at 11:22 AM, Dmitry Stogov dmi...@zend.com wrote:
  I think the AST API shouldn't use public properties.
  Using it, we will have to construct the whole tree of objects,
 duplicating
  information from AST.
  I would propose SimpleXML approach instead - construct object only for
  node(s) we currently access.
 
  So at first we will construct just single object referring to AST root.
  Then traversing it we will create and destroy objects for necessary
 nodes.
 
 I'm not sure if you've seen my astkit extension, but it does this.

 https://github.com/sgolemon/astkit


 I didn't see it before, and took just a quick look, but I like it.
 Any special reason, why you didn't implement ArrayAccess interface for
 children access?
 For me it would look natural.

 Thanks. Dmitry.



 -Sara





Re: [PHP-DEV] Feature request and RFC

2015-02-25 Thread Alexander Lisachenko
2015-02-25 13:21 GMT+03:00 Thomas Gielfeldt tho...@gielfeldt.dk:

 I have some more proposals for how to implement this interface. Should we
 create an RFC for purposes of discussion, or do you usually do this in the
 mailing lists?



Best interface is described by the one single method: sort() that accepts
optional flags and callback function:

So,

interface Sortable {
const ASC = 1;
const DESC = 2;
const SORT_REGULAR = 4;
const SORT_NUMERIC = 8;
// more consts here...

public function sort($flags = 0, callable $callback = null);
}

Callback will accept key and value pair.


Re: [PHP-DEV] Feature request and RFC

2015-02-25 Thread Alexander Lisachenko
2015-02-25 13:37 GMT+03:00 Thomas Gielfeldt tho...@gielfeldt.dk:

 Yeah, but the problem with this, is that your class' sort method, you
 have to implement all the possible permutations the flags can produce. This
 basically just squeezes the 11 functions into 1. The 1 interface with
 sort() and usort() splits this into 2 functions (8+3). With that in mind,
 I'm more inclined to choose the 4 interface approach.



For that case, move all configurations to the several classes and configure
these flags in the concrete constructors. Interface will be more simple:

interface Sortable {
const ASC = 1;
const DESC = 2;

public function sort($direction = self::ASC, callable $callback = null);
}

class KeySorter implements Sortable {}


[PHP-DEV] [Discussion] Last chance for case-sensitive engine

2015-02-23 Thread Alexander Lisachenko
Morning!

I want to ask this question one more time before PHP7 feature freeze: can
we  the engine case sensitive from PHP=7.0?

There is a draft for that: https://wiki.php.net/rfc/case-sensitivity
(mostly empty), so I decided to ask this question in the internals mail
list.

Pros: more simple O(1) hash table checks for properties, functions,
methods, classes without strtolower normalization on the engine/parser
level. Consistency with unicode class names (yes, they are case sensitive,
check http://3v4l.org/ia0pc), consistency with exisiting PSR0,4 standards
(case sensitive mapping of class names to the file names)

From my experience, all modern PHP framework don't use case-insensitive
code, so chance to break anything for them is really low.

Cons: on the extension level things aren't so good and can be some BC
breaks (like with phpng)

Possible ways:

1) Keep PHP engine case-insensitive for PHP7
2) Make PHP engine case-sensitive since PHP7 with possible minor BC breaks
in the extensions (this breaks can be easily fixed)
3) Add a compile-time switch, eg. --with-case-sensitivity to the
configuration to have an ability to build PHP with sensitivity and make
this option enabled by default since next major version (PHP=8.0). Add
deprecation notices in 7.x

Thoughts?


Re: [PHP-DEV] [RFC][Discussion] Parser extension API

2015-02-18 Thread Alexander Lisachenko
2015-02-18 22:22 GMT+03:00 Dmitry Stogov dmi...@zend.com:

 I think the AST API shouldn't use public properties.
 Using it, we will have to construct the whole tree of objects, duplicating
 information from AST.
 I would propose SimpleXML approach instead - construct object only for
 node(s) we currently access.


What about Generators? They can be used nicely for handling AST data. And
each node can be constructed as needed during the traversal. Probably this
way is better than ArrayAccess


Re: [PHP-DEV] [RFC][Discussion] Parser extension API

2015-02-18 Thread Alexander Lisachenko
 I'm okay with having stuff like -getKindName() on the nodes, however I'd
 still keep around the free-standing functions, because they can be used
 without a node (i.e. you only need the kind AST_FOO and not an instantiated
 node).


I think that getting name of kind is useless without value of kind.
According to the RFC, there is only one way from user land to get a kind of
node: ask a parser for an AST, that will contain nodes. Is there any reason
to do getKindName(1), where 1 - is just integer value. I can't see how it
can be useful, this information is fully related to the node.

I also don't see why we need ParserEngine::parse() instead of just a
 (namespaced) parse() function. Not a fan of unnecessary wrapper classes.


I think that PHP is ugly enough :) We should try to use namespaces and
classes with methods to provide a better experience for user land
developers. Classes allow for logical composition of common functionality,
provides autocompletion in IDE and can be considered as step to
standardization of core API. (Today I discussed this question with
colleagues that will be great to have all system classes in Php namespace
for PHP=7.0)

I know, that on engine level, classes aren't native, but you should think
about how this feature will be used by developers. Because, creation of API
is one-time process, but imagine how many times it will be used by
developers. I think, it will be more polite to provide OO-code for modern
API.

What's the advantage of this? Most leaf nodes will be zval nodes and I feel
 it would be rather inconvenient if they'd all have extra wrappers. Is there
 some specific problem with including the values directly?


Yes, reason here is the same as for `token_get_all()`. I hear so many WTFs
when value can be either simple character or array. Much harder to work
with inconsistent data and many libraries performs additional steps to
provide better usability (see
https://github.com/Andrewsville/PHP-Token-Reflection/blob/1c5ff91ee6877d1fb0f60fab3e3fc562bdb02684/TokenReflection/Stream/StreamBase.php#L100-L108
or
https://github.com/lisachenko/go-aop-php/blob/3c381e243367096d47dc9676b3ad7445d7720ba9/src/Instrument/Transformer/MagicConstantTransformer.php#L117
)

So, each element should be represented as common node, this will simplify
usage of API.


Re: [PHP-DEV] [RFC][Discussion] Parser extension API

2015-02-18 Thread Alexander Lisachenko
2015-02-18 17:59 GMT+03:00 Nikita Popov nikita@gmail.com:

 Alexander, I would recommend you to split this into two RFCs, one dealing
 only with AST export (and maybe pretty printing) and the second one with
 the compilation hooks. There's probably a few questions about the export
 API that should be discussed that will be forgotten if everyone focuses on
 the more complicated, and probably not yet relevant, question of
 compilation hooks.



Hello, Nikita! Thanks for you thoughts!

Sounds reasonable for me, because of short timeframe for PHP7. Let's go
with the first part of RFC, because second part is really cumbersome and
can be applied later, eg. in 7.1 I will split this RFC into two parts and
mark first part for 7.0.

About first part, do you agree with proposed classes and namespace
`Php\Parser`? I want to propose to use classes for parser API instead of
pure functions because it can give more usable OO-API for future needs.

There is one more notice regarding to the zval nodes, they should be also
exported as objects, not as values. I think we should export coherent nodes
for everything.


Re: [PHP-DEV] [RFC][Discussion] Parser extension API

2015-02-17 Thread Alexander Lisachenko
2015-02-17 16:35 GMT+03:00 Rowan Collins rowan.coll...@gmail.com:

 I think should is OK for extensions, but not for userland hooks. There
 needs to be a very firm definition of the right and wrong way to implement
 these hooks, which can at the very least warn the user when they are
 slipping into undefined behaviour.



Thanks for this point. Added this question to the list of open issues in
RFC. My vision is to update a documentation with clear description, why
parser extensions should be registered statically without conditions.
Parsing process and limitations should be also described in the RFC.


2015-02-17 16:35 GMT+03:00 Rowan Collins rowan.coll...@gmail.com:

 The other alternative is to go to the other extreme, and have the
 extensions scoped to a particular file, more like Perl pragmas. Dare I say
 we could use the declare() syntax that everyone seems to have an irrational
 hatred of?

 declare(pragma=Example\DbcParserExtension);


Ouch ) Don't like this way at all, because extensions should process all
files, even if it's not marked with some hints. What I want to see is PHP
analog of Java bytecode compilers, they can transform an original source
code into specific tokens and provide custom extensions on top of that. So,
I want to choose between php.ini option and explicit methods. Let's see
another opinions.

Thanks!


Re: [PHP-DEV] [RFC][Discussion] Parser extension API

2015-02-17 Thread Alexander Lisachenko
Hello, Lars!

2015-02-17 22:09 GMT+03:00 Lars Strojny l...@strojny.net:

 Looks cool and I could see a couple of interesting possibilities arising.
 One thing: any particular reason ExtensionInterface is static? I could see
 a couple of benefits having extensions carry state and registerExtension()
 taking an instance of ExtensionInterface, not a class name. What do you
 think?


Thanks for the positive feedback! My first thought was to use instances for
extensions: https://gist.github.com/lisachenko/ffcfdec4c46e01864b33.
However, I have a doubts that this will introduce additional possibilities
for side-effects, when extensions can be configured
differently/loaded/unloaded. In this thread some people noticed this fact
too and suggested to add a restrictions for preventing conditional parsing
of the source code.

So, static method and static registration was chosen to reduce a number of
possible conditional extensions. This has some disadvantages (testing,
configuration, etc), but should give better experience with parsing
behavior.


Re: [PHP-DEV] Annotations in PHP7

2015-02-17 Thread Alexander Lisachenko
2015-02-17 19:25 GMT+03:00 Dmitry Stogov dmi...@zend.com:

 I think yes,
 However, Alexander thinks differently
 https://wiki.php.net/rfc/parser-extension-api
 Of course this is not for 7.0


This RFC consists of two parts: parsing API and parser extension API. Last
one can be rejected, however it can be perfectly connected with annotation
RFC (if AST will be used as values)


As for annotations, general use-case is appreciated. This can be extended
later in future versions of PHP. Therefore, annotation syntax should allow
to define key and values. Value can be valid expression (AST? concrete
node? compiled value?) or can recursively contain nested annotations.


Re: [PHP-DEV] RFC Proposal

2015-02-17 Thread Alexander Lisachenko
2015-02-17 20:35 GMT+03:00 Tim Bezhashvyly tim.bezhashv...@gmail.com:

 this is my first RFC proposal and I am not sure if in this email is
 supposed to contain all RFC details or just a brief idea .. which is to
 drop PHP constants in favour of “final immutable variables.


Hello, Tim

Recently, I asked this question on internals
http://www.serverphorums.com/read.php?7,1123371 about immutable variables
and objects. Please, continue it if you want to discuss it, this will keep
the context of thread in one place.

However, no need to drop constants, but only to add an additional behavior
for objects and variables.

Thanks!


[PHP-DEV] [RFC][Discussion] Parser extension API

2015-02-17 Thread Alexander Lisachenko
Hello, internals!

I want to introduce a RFC for providing a userland API for accessing an
Abstract Syntax Tree of the source code and to provide userland parser
hooks for source code modification:
https://wiki.php.net/rfc/parser-extension-api

Thanks!


Re: [PHP-DEV] [RFC][Discussion] Parser extension API

2015-02-17 Thread Alexander Lisachenko
2015-02-17 15:06 GMT+03:00 Leigh lei...@gmail.com:

 Does the AST provided by the internal parser provide all of the
 information required to be able to turn it back into source code?

 Yes, this should be possible, via zend_emit_op*() and zend_compile*()


2015-02-17 15:06 GMT+03:00 Leigh lei...@gmail.com:

 Re: Extending the parser from PHP userland.

 This I don't like so much.

 To be honest I hoped this would be an API to extend the parser from
 PHP extensions :) I think letting userland fiddle directly with the
 compilation process is just asking for trouble.


Expected reaction ) However, it would be nice to have such API on userland
too (on engine level this can be a hook too). This will give an instrument
for building custom things on user side, but will keep PHP engine clear
from a lot of stuff, which can be implemented by users. Nice example is
Design-By-Contract validation, it can be easily done via parser hooks.


Re: [PHP-DEV] [RFC][Discussion] Parser extension API

2015-02-17 Thread Alexander Lisachenko
2015-02-17 15:09 GMT+03:00 Benjamin Eberlei kont...@beberlei.de:

 The visitor API is the essential part here and you left it out.


Yes, I decided not to put Visitor in the RFC (this was added as open
question to the RFC). But this part can be discussed in the case of general
acceptance.


2015-02-17 15:09 GMT+03:00 Benjamin Eberlei kont...@beberlei.de:

 How does this work with Engine Extensions, are they considered for all
 require/include's *after* the registrtion? How does this work with opcache?


Yes, parser extensions will be called for all require/include/evals after
registration. This part is transparent for opcache, because opcache just
stores an opcodes for the file. AST is parsed only once for each file, then
hooks can transform the AST and after that compiler will produce a final
opcodes that can be stored for that file in the opcache. So, I expect no
impact on opcache logic.


Re: [PHP-DEV] [RFC][Discussion] Parser extension API

2015-02-17 Thread Alexander Lisachenko
2015-02-17 15:29 GMT+03:00 Benjamin Eberlei kont...@beberlei.de:

 Well not really, depending on the path towards a require a parser
 extension is already registered or not. Or you have conditional
 registration of extensions. So you could load a file with an extension
 registered, but it still serves the old opcodes for that file.



Technically, this will be possible, however, Parser Extensions should be
registered ASAP during bootstrap process, near spl_autoload_register(),
stream_wrapper_register(), stream_filter_register(), etc..
So, no conditional code hooks should be used for that. But this can be the
consistent with stream wrappers, filters and autoloaders. Developer can
decide what he need to enable some features.

One more possible way for this RFC is to remove these register/unregister
methods from the `Php\Parser\Engine` class and add an option to the php.ini
with list of classes to load. This option can be adjusted then per
project/directory. Is this more suitable?

Thanks!


Re: [PHP-DEV] [RFC][Discussion] Parser extension API

2015-02-17 Thread Alexander Lisachenko
2015-02-17 15:48 GMT+03:00 Leigh lei...@gmail.com:

 So: Internal Parse AST - Extension Parse AST - Generate OpCodes -
 OpCache?


Yes, it's correct flow.

2015-02-17 15:48 GMT+03:00 Leigh lei...@gmail.com:

 So if the parser extension does anything dynamic, then OpCache will
 have the wrong version cached.


This restriction is intended by design, no dynamic changes are allowed.
However, if you need, then you can disable an opcode cacher and do anything
you want.

Your example is actual for production mode of PHP too, when
opcache.validate_timestamps=0 or apc.stat=off. Parsing will be performed
only once, then you need to clear cache manually to reload changes from the
file system. So, parser extension works transparently and used only when
needed to process an AST.


Re: [PHP-DEV] Annotations in PHP7

2015-02-16 Thread Alexander Lisachenko
2015-02-16 15:31 GMT+03:00 Benjamin Eberlei kont...@beberlei.de:


 My question is how do i evaluate this at runtime? I suppose a function is
 necessary like evaluate_ast(...), but  that requires passing the context.
 many many open questions and as nikic points out this should probably be
 delayed to 7.1 because it all should be discussed and specified.


This will be like pretty simple to parse:
// For scalars:
$attributes = (new ReflectionMethod(some::class, 'method))-getAttributes();
$cacheableNode = $attributes[Cacheable::class] ?? new
Php\Parser\Node(AST_TYPE_VALUE, 50);
$cacheTime = $cacheableNode-value;

// For more complex things, like expressions or constant, runtime
evaluation can be performed.
$codeNode = $attributes[Php\Contract\Requires::class] ?? new
Php\Parser\Node(AST_TYPE_STATEMENT, '$this-value =0');
$code = (string) $codeNode;
$result = eval($code);


Re: [PHP-DEV] Annotations in PHP7

2015-02-16 Thread Alexander Lisachenko
2015-02-16 15:12 GMT+03:00 Benjamin Eberlei kont...@beberlei.de:

 but what is the API of an AST node and how does the visitor look like?



I have a draft for that:
https://gist.github.com/lisachenko/ffcfdec4c46e01864b33 This is extended
version for php-ast extension that I want to propose for PHP.


[PHP-DEV] Re: Annotations in PHP7

2015-02-16 Thread Alexander Lisachenko
2015-02-16 14:19 GMT+03:00 Dmitry Stogov dmi...@zend.com:

 annotations ::= { annotation }.
 annotation   ::= '' STRING '' | '' STRING '(' expr ')' ''.

 where expr is regular PHP expression.



Hello!

Really like this syntax, actually you steal my thoughts )) I want to call
this metadata, not an annotations. Just key-value storage for any top-level
elements (namespaces, classes, functions, methods, properties, etc).

Value can by anything, acceptable by PHP parser, then it will be possible
to provide an API to get this AST node as-is and to add a logic layer on
top of this. (I'm still waiting for the RFC karma)

For annotations, it should be possible to use ClassName::class
constant. Additionally, nested metadata should be supported.

Thanks!


Re: [PHP-DEV] Annotations in PHP7

2015-02-16 Thread Alexander Lisachenko
2015-02-16 14:42 GMT+03:00 Dmitry Stogov dmi...@zend.com:

 the idea to not evaluate non-constant expressions at all, but just keep
 AST and provide interface to read it.
 PHP extensions should be able to use them as they like. (evaluate or
 insert into AST of function(s), etc).

 Thanks. Dmitry.



It's a good decision, userland frameworks, such as Doctrine/Go! AOP/etc
will use this AST nodes and node visitors to provide an extension
mechanism. Strong +1 here for AST nodes.


Re: [PHP-DEV] Design by Contract

2015-02-10 Thread Alexander Lisachenko
Hello, internals!

DbC is good thing, but the way you want to do this via language changes is
really awful. Why do you want to add more custom features into the
language, instead of providing an API to extend it in a more natural way by
framework developers?

Many existing implementation of DbC is just kind of bytecode compilers and
IDE tools. Main idea of DbC is to help developer with writing a better code
without errors. But then, during compiling (production mode) all checks
will be removed.

Am I one who think that this code is looking weird?

public function destroy($id)
require(strlen http://www.php.net/strlen($id)  10)
return(is_bool http://www.php.net/is_bool($))
{
@unlink http://www.php.net/unlink($this-path . $id);
}


This part of code is breaks block structure of function, adding custom
part of code, which is not related to the function logic itself.

Instead of doing this weird syntax only for personal fun, just think
about more general usages of parser and assertions.
As you know, I'm working with aspect-oriented programming in PHP and
have a library for that. And it wasn't easy to implement it, because
there is no API for that from PHP. This techniques can be also used
for DbC as well.

So, my suggestion is to drop current rfc and start more general one,
called PHP Language Extension API, which will include an API for
defining metadata and API for opcode manipulation. Compare previous
example with another one with plain metadata:

[Require = strlen http://www.php.net/strlen($id)  10)]
[Return = is_bool http://www.php.net/is_bool($__result))
public function destroy($id)
{
@unlink http://www.php.net/unlink($this-path . $id);
}

This code then will be parsed and PHP hooks that were registered by
register_parser_extension() will be called and extension will
produce a valid opcodes for that for method destroy(), by modifying AST-node.

This way is much elegant and can be reused later for many features,
like Design By Contracts, native SQL support syntax in PHP (LINQ),
Aspect-Oriented Programming, hooks and much more.

Just stop to create custom features in the engine itself and give this
work for framework and PHP-extension developers.




2015-02-10 13:32 GMT+03:00 Lester Caine les...@lsces.co.uk:

 On 09/02/15 23:47, Yasuo Ohgaki wrote:
  The RFC draft is ready.
  https://wiki.php.net/rfc/dbc2

  These contracts are evaluated development time only. Therefore, there is
 no performance penalty with DbC.

 Sorry but that makes no sense to me at all. If this is something only to
 use with an IDE then why does it have to have anything that is visible
 at 'run time'? This seems to be going down the track of we will be
 compiling this eventually and that is just not what PHP *IS* about.
 These are more hints, but assume that at runtime what they define is not
 relevant?

 ALL of this discussion on type hinting how ever it is handled is simply
 sidestepping the major plus on PHP with associative arrays. I see no
 point expanding every database record read to 'magic access functions'
 for multiple variables and it *IS* the scalar values stored in these
 arrays that needs the 'hint/constraint' control.

 I am getting even more confused about just what all the different
 factions are trying to achieve. Yes I know I can totally ignore all of
 it, but with my current tools losing traction because of all the 'better
 ways of working' what in my opinion IS the best way to allow different
 factions to add their own pet style is drowning simple clean solutions
 such as docblock.

 --
 Lester Caine - G8HFL
 -
 Contact - http://lsces.co.uk/wiki/?page=contact
 L.S.Caine Electronic Services - http://lsces.co.uk
 EnquirySolve - http://enquirysolve.com/
 Model Engineers Digital Workshop - http://medw.co.uk
 Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

 --
 PHP Internals - PHP Runtime Development Mailing List
 To unsubscribe, visit: http://www.php.net/unsub.php




Re: [PHP-DEV] Design by Contract

2015-02-10 Thread Alexander Lisachenko
2015-02-10 14:56 GMT+03:00 Patrick Schaaf b...@bof.de:

 Ahem. Any open ended API-for-frameworks will A) force me to pick a
 framework and bend to the way it wants these things to look, and B) result
 in fragmentation and incompatibilities for any two pieces of code/library
 developed with different such frameworks in mind. That will be a total mess.



It's another task for another people, typically for standartization group,
like PSR, JSR, PEP, etc. Framework developers should rely on interfaces and
should provide interfaces. For Java world this works (some ideas here
http://java.dzone.com/articles/jsr-305-and-design-contract)

If put all the things into the PHP core, it will become much bigger, more
slower and hard to maintain. Later posts describes EOL for some extensions
and SAPIs, but this place will not be clean, because another custom feature
XXX is landed on free space.

I would like to see a language with good extension API. For now, it's
almost impossible to extend a parser, even from extension level (however,
PHP7 will have a hook for that, thanks God).


Re: [PHP-DEV] Design by Contract

2015-02-10 Thread Alexander Lisachenko
2015-02-10 15:10 GMT+03:00 Alexander Lisachenko lisachenko...@gmail.com:

 I would like to see a language with good extension API. For now, it's
 almost impossible to extend a parser, even from extension level (however,
 PHP7 will have a hook for that, thanks God).



To understand how it can be implemented, just read about Checker Framework
(Java) http://types.cs.washington.edu/checker-framework/

...The Checker Framework enhances Java’s type system to make it more
powerful and useful. This lets software developers detect and prevent
errors in their Java programs. The Checker Framework includes compiler
plug-ins (checkers) that find bugs or verify their absence. It also
permits you to write your own compiler plug-ins...

This is built on top of reflection+annotation+parser extension.
Why not to implement this for PHP? From my point of view, this is just an
additional feature, that can be used by limited number of developers.


Re: [PHP-DEV] Design by Contract

2015-02-10 Thread Alexander Lisachenko
2015-02-10 15:20 GMT+03:00 Dmitry Stogov dmi...@zend.com:

 I thought about this way, and you are welcome to start composing another
 RFC. it makes sense and has its advantages.
 Unfortunately, it relays on many unavailable features that has to be
 designed as well (annotations, AST manipulation, opcode manipulation), but
 may be this is a right road.



Thanks, Dmitry! Your position is clearly highlight my vision, it's not so
easy, but maybe it will bring us much more profit at the end.


2015-02-10 15:20 GMT+03:00 Dmitry Stogov dmi...@zend.com:

 D and Effiel approach may work as well, but if you like another
 (annotation based) approach - be involved into development.
 At first we'll need 3-rd RFC that defines all the things that must be
 implemented.
 I may help, with RFC, design and implementation.


Thanks, your help is really appreciated ) I'l try to start another one RFC
about this API, let's have a look what can be done.


Re: [PHP-DEV] Design by Contract

2015-02-10 Thread Alexander Lisachenko
2015-02-10 15:35 GMT+03:00 Pavel Kouřil pajou...@gmail.com:

 Hello,

 maybe you could try to consult your ideas with Ivan Enderlin. He
 mentioned in previous emails (for instance
 http://news.php.net/php.internals/82245) that he would prefer some
 AOP/hook-based approach to DbC as well, so it may be compatible with
 your mindset.


Yes, I know about Praspel, it's quite a good implementation, but for
specific case. My implementation of DbC is built on top of AOP and can be
described with only one (!) aspect and few annotations. If you are
interested in it, you could look across wiki
https://github.com/lisachenko/php-deal/wiki or even open an aspect class
itself
https://github.com/lisachenko/php-deal/blob/master/src/PhpDeal/Aspect/ContractCheckerAspect.php
to see an advices that will be triggered as custom hooks before/after or
around original method invocations.

I think, that AOP-based solution is pretty nice: it's only for development
mode. Annotations are not parsed for production mode and looks like a good
documentation, this can be improved later with BDD (Gherkin) to define a
contracts in human-readable format.

@Contract\Verify(Given $amount is positive)
@Contract\Ensure(Result is changed from $old to $old+$amount)

So, it can be a good idea to discuss this topic with Ivan Enderlin. Maybe
he can help me with RFC too.


Re: [PHP-DEV] Design by Contract

2015-02-05 Thread Alexander Lisachenko
2015-02-05 16:07 GMT+03:00 Dmitry Stogov dmi...@zend.com:

 In general it's should be possible to provide PHP API to manipulate with
 AST and write compiler extensions in PHP.
 Looks promising.. :)
 Anyway, If you are interested - start working on it.



Actually, it's almost done by Nikita Popov: https://github.com/nikic/php-ast.
Missing part is to put this extension into PHP core, create an interface
for hooks and then give PHP hooks a control during parsing of source code.

So maybe just make a vote to include this API into core? This will give a
lot of food for thoughts and implementations of AOP, DbC, SQL-like native
syntax and much more. From PHP Core developers it will be only the
implementation, all other things can be easily extended by userland
developers.


Re: [PHP-DEV] Design by Contract

2015-02-05 Thread Alexander Lisachenko
2015-02-05 15:32 GMT+03:00 Dmitry Stogov dmi...@zend.com:

 Hi Alexander,

 Defining contracts through doc-comments is also possible, but this way is
 not native.
 On the other hand, if you already have this implemented, we may just reuse
 it.



Thanks, Dmitry! This would be a really nice feature on engine-level.
Ideally, for PHP7-8, I would like to see a hook system from compile-level
to userland, to define a language extension. This feature is highly
required for custom DSLs and much more. DbC technique can be also
implemented as parse-time weaver. E.g. we define a parser-extension:

register_parser_extension(ContractExtension::class);

this class will receive an AST of PHP file and check interesting nodes.
This node can be annotation or something else:

[Contract::Invariant = $this-value  0]
class Test {
public $value = 100;
public function foo($newValue) {
$this-value = $newValue;
}
}

and parser extension change the compiled source code by inserting this
check into methods:

[Contract::Invariant = $this-value  0]
class Test {
public $value = 100;
public function foo($newValue) {
$this-value = $newValue;
assert($this-value  0); // Inserted by parser extension (via
opcodes)
}
}

Is it possible to do this?


Re: [PHP-DEV] Design by Contract

2015-02-05 Thread Alexander Lisachenko
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($amount0  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





Re: [PHP-DEV] Design by Contract

2015-02-05 Thread Alexander Lisachenko
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($amount0  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




Re: [PHP-DEV] [RFC] Immutable variables and objects

2015-02-02 Thread Alexander Lisachenko
I want to add a link here to the Java article about Value Types, this
information is quite interesting:
http://cr.openjdk.java.net/~jrose/values/values-0.html

Probably, immutable value objects will be soon in Java world according to
this information:


 Conclusion

 Along with the questions, we believe we have enough answers and insights
 to begin prototyping value types, and verifying our thesis. That is, we
 think it quite likely that a restricted class-like type can be made to look
 enough like a primitive to be worth adding to the language and VM.


2015-02-02 13:01 GMT+03:00 Rowan Collins rowan.coll...@gmail.com:

 Lester Caine wrote on 02/02/2015 09:19:

 This is probably because I still don't understand objects, as I still
 just consider them as arrays with a few more complex elements. I STILL
 work on the basis that is I pass by reference, I can make modifications
 to the data while if I don't I get a copy and have to pass the copy back
 if I need the original changed. This used to be all very simple, so when
 did it stop working? This may explain why I get into trouble with stuff
 that has been working for years but after 'modernising' starts throwing
 problems :(


 Since PHP 5, and in most other languages, objects are passed with an extra
 level of indirection, almost but not quite the same as pass-by-reference.
 So there are actually three ways a variable can be passed (or assigned):

 - scalar by value - an assignment to the variable changes only that
 variable
 - scalar by reference, using  - both variable names point to the same
 variable, and assigning a value to one assigns it to both
 - object by value - an assignment to the variable still only changes that
 variable, BUT two variables can point at the same object can both modify
 its internal state. So if you have $current_user = getCurrentUserObject();
 then saying $current_user = null; is changing its value, so would only
 change that variable, but $current_user-setPassword('1234'); is not, so
 the change would be visible from all variables pointing at that object.

 Immutable parameters for scalars and arrays are simple: currently you can
 use a by-value parameter as a local variable in your function, but you
 might want to avoid the confusion of this: function foo( const $bar ) {
 $bar = 42; // ERROR } or foo( const array $bar ) { $bar[] = 42; // ERROR }

 Immutable parameters for objects are complicated, because foo( const $bar
 ) { $bar-value = 42; } is not technically changing the *value* of that
 object, but it would be useful to have an enforcement that it wouldn't
 happen.

 Hope that clarifies things a bit.

 Regards,
 --
 Rowan Collins
 [IMSoP]
 ||



Re: [PHP-DEV] [RFC] Immutable variables and objects

2015-02-01 Thread Alexander Lisachenko
Hello, internals!

2015-02-01 4:01 GMT+03:00 Andrea Faulds a...@ajf.me:

 I think having some means to create value type classes (i.e. PHP 4-style
 classes) would be beneficial. These classes would have the same always-copy
 or copy-on-write behaviour that PHP’s scalar types and arrays have. They’d
 be performant compared to immutable classes like PSR-7’s, because
 operations mutate the value in-place if possible, rather than creating a
 new class. They’d also be nicer to use, because you can change the value
 imperatively rather than having to chain together return values. But you
 keep the main advantages of immutable types: no spooky action at a
 distance, no explicit copying needed.



Agree in that point with you, this can be a good instrument if implemented
in PHP. I see a good point in it by using this with interfaces and const
modifier for parameters:

class Foo {
public function bar(const Baz $object); // Require an instance to be
passed as copy
}

This should be used as weakly immutability for places where changes of
object is not expected. However, we can call methods on $objet, e.g.
setters.

The same will be useful for simple object variables:

const $object = new stdClass;
$object = 123; // Exception, can not change const variable
$object-field = 456; // Exception, can not change public properties for
const objects

$anotherObject = $object; // Copy on write
$anotherObject-field = 123; // ok to change local copy

However, we should not worry about setters (if present):

class MutableObject {
public $field = 42;
public function setField(const integer $newValue) {
$this-field = $newValue;
}
}

// let's create immutable object instance for that

const $instance = new MutableObject();
$instance-field = 56; // Exception, can not change public properties for
const objects
// BUT, no checks for setters
$instance-setField(56);
echo $instance-field; // outputs 56

I think temporary immutability for objects can solve a lot of extra checks.
For example, my previous code allows to drop extra getters
($instance-getField()) for simple classes, when we just want to work on
our local copy of object in read-only mode. With this feature
DateTimeImmutable functionality can be implemented like that:

const $now = new DateTime();
$future = $now; // Copy on write
$future-modify('+1 day'); // only $future variable is modified
echo $now-format(DATE_RFC822); // unchanged


On 1 Feb 2015, at 00:55, Stanislav Malyshev smalys...@gmail.com wrote:

 For all this, I'd like to ask - why? Immutable object are very useful in
 concurrency applications, since they allow to avoid expensive
 synchronization costs and make it much easier to reason about system's
 state (which is arguably impossible to predict with mutable objects in a
 parallel system). But PHP has no parallelism. So which benefit would
 that provide? If you want an immutable object, just make all properties
 protected and provide getters but not setters. This is easily doable
 without any keywords.


Yes, parallelism is not present in PHP (except pthreads extension), so this
requirement for temporary immutability of variables is less than in
multi-threaded applications with IPC. But I think that main advantage of
this modifier (immutable) is to add extra protection and assumption for
developers to bypass extra getters (sorry, Doctrine) and to allow more
safer code.

Passing a copy of object (should this be deeper clone or not?) as an
argument to the function is nice feature too, IMO. We *explicitly* mark an
argument as immutable for method body, so no direct changes will be
performed on this instance and no overhead for calling getters.

Should I try to write an RFC for that?


Re: [PHP-DEV] [RFC] Immutable variables and objects

2015-01-30 Thread Alexander Lisachenko
2015-01-30 18:07 GMT+03:00 Andrea Faulds a...@ajf.me:

 This approach wouldn’t solve the problem you’re describing. You *still*
 need to produce a new request object, because the request object is
 immutable. The mutability of its *properties* isn’t the issue.



Thank you for this answer. However, pay an attention to the last part of my
suggestion. To create a mutable copy of immutable object it will be
possible just to make an assignment (this will create a copy/clone) to a
local mutable variable and adjust it for your needs.

example:

public function handleRequest(const Request $request) { // Mark $request as
immutable for body
// we can not change $request variable itself
// but if need, we can only initialize a copy of it
// $request-url = 'https://evil.com'; // Exception will be there

$mutableSubRequest = $request; // copy of immutable object or maybe a
direct Copy-on-Write?
$mutableSubRequest-uri = 'https://example.com'; // It's ok to modify
our local copy of an object
$this-kernel-handleRequest($mutableSubRequest);
}

2015-01-30 18:07 GMT+03:00 Andrea Faulds a...@ajf.me:

 Hi Alexander,

  On 30 Jan 2015, at 13:07, Alexander Lisachenko lisachenko...@gmail.com
 wrote:
 
  Hello, internals!
 
  Today I was looking at PSR-7 and discovered this part of code:
 
  $body = new StringStream(json_encode(['tasks' = [
 'Code',
 'Coffee',
  ]]));;
  $request = $baseRequest
 -withUri($uri-withPath('/tasks/user/' . $userId))
 -withMethod('POST')
 -withHeader('Content-Type' = 'application/json')
 -withBody($body);
  $response = $client-send($request);
 
  What is wrong here? Emulated immutability. All methods will create a
  separate instance of request, so
  $baseRequest-withUri()-withMethod()-withHeader()-withBody() will
 create
  total 5 object instances. It's a memory overhead and time consumption for
  each method call.

 Yes, I also think this is unfortunate.

  What I want to discuss is true immutability flag for variables and
  parameters. There are a lot of languages that use final or const
  keywords to prevent modification of variables. We can use this approach
 by
  extending language syntax as following:

 This approach wouldn’t solve the problem you’re describing. You *still*
 need to produce a new request object, because the request object is
 immutable. The mutability of its *properties* isn’t the issue.

 If you want to avoid creating five different objects, you’d need to
 implement value-type objects that are passed by value and use
 copy-on-write. Basically, you’d need to re-add PHP 4 style classes.

 Thanks.
 --
 Andrea Faulds
 http://ajf.me/







[PHP-DEV] Re: [RFC] Immutable variables and objects

2015-01-30 Thread Alexander Lisachenko
It can be a good idea to pass an object to the const parameter in php4
style (copy on write). Then original object will be untouched.

The same will be for local objects with const flag.

No reassignments. Always pass a copy (like with arrays now)

пятница, 30 января 2015 г. пользователь Andrea Faulds написал:

 Hi,

 This accidentally went off-list, forwarding for everyone else’s sake.

  Begin forwarded message:
 
  Date: 30 January 2015 16:01:43 GMT
  Subject: Re: [PHP-DEV] [RFC] Immutable variables and objects
  From: Alexander Lisachenko lisachenko...@gmail.com javascript:;
  To: Andrea Faulds a...@ajf.me javascript:;
 
 
  2015-01-30 18:41 GMT+03:00 Andrea Faulds a...@ajf.me javascript:;
 mailto:a...@ajf.me javascript:;:
  So what you’re suggesting is a special type of variable modifier which
 makes that variable have completely different copying semantics to usual?
 
  That would be quite strange, I don’t see that getting much support.
 
 
 
  Yes, this should affect a variable state and passing an object to the
 function to make it immutable. But this technique (weakly immutable) is
 quite useful in several languages. For example, in Java:
 
  final int j = 42;
  j = 43; // does not compile. j is final so can't be reassigned
  or alternative in C++
  const int j = 42;
  j = 43; // does not compile. j is const so can't be reassigned
 
  One more example is passing an argument to function as immutable in C++
 with const and then make a mutable copy of object with const_cast.
 
 Thanks.

 --
 Andrea Faulds
 http://ajf.me/







[PHP-DEV] [RFC] Immutable variables and objects

2015-01-30 Thread Alexander Lisachenko
Hello, internals!

Today I was looking at PSR-7 and discovered this part of code:

$body = new StringStream(json_encode(['tasks' = [
'Code',
'Coffee',
]]));;
$request = $baseRequest
-withUri($uri-withPath('/tasks/user/' . $userId))
-withMethod('POST')
-withHeader('Content-Type' = 'application/json')
-withBody($body);
$response = $client-send($request);

What is wrong here? Emulated immutability. All methods will create a
separate instance of request, so
$baseRequest-withUri()-withMethod()-withHeader()-withBody() will create
total 5 object instances. It's a memory overhead and time consumption for
each method call.

What I want to discuss is true immutability flag for variables and
parameters. There are a lot of languages that use final or const
keywords to prevent modification of variables. We can use this approach by
extending language syntax as following:

const $text = Some message; // defines an immutable variable that can not
be modified.
$text .= foo; // Exception: can not change the immutable variable

class Test {
public final $value; // final keyword defines immutable property, but
it isn't initialized yet so allows only one assignment, then will be
immutable
public function __construct(const $value) // Argument is declared as
immutable with const keyword, can not be changed in the function body
{
$this-value = $value;
// $value = 456; // will throw an exception
}
}

$obj = new Test(42);
echo $obj-value; // Direct access to the property, result is 42

$obj-value = 100; // Exception: can not change the immutable (final)
property

Immutable variable can not be made mutable, but it can be assigned to the
separate mutable variable (copy on write). Example:

const $text  = Some message;
$anotherText = $text;
$anotherText .= modified

On the engine level this immutable variables and parameters can be
effectively optimized by using IS_TYPE_IMMUTABLE for zval. This can result
in achieving better performance and various JIT-optimizations.

Thoughts?


Re: [PHP-DEV] [RFC] Default constructors

2014-11-18 Thread Alexander Lisachenko
Hi!

2014-11-18 12:20 GMT+03:00 Stanislav Malyshev smalys...@gmail.com:


 I'd like to propose the following RFC, which in short would allow any
 method to call parent ctor (and some other methods) even if such is not
 explicitly defined:


+1 for defining base class for all classes and addition of default
constructor implementation in it.

One more example with inconsistent ctors handling via Reflection:
http://3v4l.org/Tjn82


Re: [PHP-DEV] Annotation PHP 7

2014-11-05 Thread Alexander Lisachenko
2014-11-05 17:02 GMT+03:00 Marco Pivetta ocram...@gmail.com:

 For example, this alternative approach perfectly fits the current
 doctrine/annotations use-case:

 use Doctrine\ORM\Mapping\Entity;
 use Doctrine\ORM\Mapping\Table;
 use Doctrine\ORM\Mapping\Id;
 use Doctrine\ORM\Mapping\GeneratedValue;
 use Doctrine\ORM\Mapping\Column;

 [Entity::class = []]
 [Table::class = ['name' = 'foo_table']]
 class Foo
 {
 [Id::class = []]
 [GeneratedValue::class = [GeneratedValue::UUID]]
 [Column::class = ['name' = 'bar_column', 'type' = 'string']]
 private $bar;
 }


This looks great indeed for many reasons:
1) it's a simple array
2) it can be parsed with built-in DSL syntax for PHP, so any arbitrary
evaluations with constants can be applied transparently, e.g.
[Loggable::class = ['pointcut' = self::PREFIX . 'test' ]]

3) C# uses similar syntax with square brackets for annotations:

public class Foo
{
[Display(Name=Product Number)]
[Range(0, 5000)]
public int ProductID { get; set; }
}

However, I would like to see simple markers without nested associative
arrays, e.g just put single AnnotationName::class into brackets or specify
multiple annotations in one section:

[Entity::class, Table::class = 'foo_table']
class Foo
{
  // ...
}


Re: [PHP-DEV] Annotation PHP 7

2014-11-04 Thread Alexander Lisachenko
Hi!

It would be nice to take paving the walkways approach, but last time
 we tried, IIRC we've got into something very over-engineered. Maybe if
 we try again with more restricted scope (i.e. not trying to put a DSL
 for describing arbitrarily complex data structures into it :) it would
 be more successful this time.


PHP7 has a wonderful parser, maybe it's possible to provide a general
syntax for annotations with userland hooks for arbitrary data. This
approach can give a tool for framework developers to define a node visitor
for annotations. Alternative way is to define simple key-value storage and
access it via Reflector-getAnnotations().

I want to put my huge +1 vote on annotations support in the core, because
Go! AOP uses annotations a lot for defining metadata and markers in the
code and provides an engine for advanced programming patterns and method
interception. Doctrine is good library, but this can be better on core
level.


Re: [PHP-DEV] [RFC] Using objects as keys

2014-10-27 Thread Alexander Lisachenko
Hello, internals!

 The name __hash is not final, I am open to using __toKey instead or any
 reasonable alternative, we may also include a couple of options in the
 vote if that will be a point of disagreement.

I like this idea with custom hash implementation because spl_object_hash()
is not reliable when objects are quickly created/destroyed, so hashes can
be the same for several different objects. However, will it be better to
introduce an interface for that? For example, Hashable can be a good name
(like Traversable one). Default implementation then can be a simple trait
that will be added later to the concrete class.


Re: [PHP-DEV] [RFC] Safe Casting Functions

2014-10-21 Thread Alexander Lisachenko
Hello, internals!

 Good evening,

 I am presenting a new RFC to add a set of three functions to do validated 
 casts for scalar types:

 https://wiki.php.net/rfc/safe_cast

 Please read it.

Personally I don't like this RFC because it's introducing one more way
to cast value in PHP. We already have boolval(), intval(), strlva()
functions that are not widely used in the source code, because of
dynamic nature of PHP. Developers just use value as is, assuming that
it will cast automatically where needed. This kind of casting is
typically used to prevent an attacks like this $id =
intval($_GET['id']); But this is ugly implementation from my point of
view. Binding and sanitization can do this much better.

There is also one more way to cast values with explicit casting: $id =
(int) $_GET['id']. I think that this way of doing casting is more
natural for developers to read, because many languages use the same
scheme to cast values into another types. Instead of implementing new
to_() functions, it can be nice to reuse logic of casting with
(type) $value to follow
https://wiki.php.net/rfc/scalar_type_hinting_with_cast#conversion_rules
which looks great.

Besides this, there is casting with settype($value, $type) and one
more with filter sanitization.

If this RFC will be accepted there will be one more way with own logic
of casting. And this is not so good from userland point of view.

It can be good only with OOP support for primitive types, for example
$value = '1234'; $number = $value-toInt(); $float =
$value-toFloat(), etc..

Thanks!

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [RFC] Access to aliases definition by reflection

2014-10-13 Thread Alexander Lisachenko
Hello!

 I've written an RFC which proposes to expose a namespace aliases/imports for
 user-land code.

 https://wiki.php.net/rfc/aliases_by_reflection

I think that this idea is good, however it isn't correct to keep
aliases per each class, because they are applied per scope.
TokenReflection library uses ReflectionFileNamespace for that to
define a namespace section in the file (there can be many namespaces
per one file) and provides an API to fetch aliases. It also provides
extended classes with link to the ReflectionFileNamespace.

PHP doesn't have a Reflection for that kind of object, however it can
be nice to add it to keep an information about namespace start
line/end line, file name, imported aliases and defined constants. And
add a getters for all other reflection classes, for example, (new
ReflectionClass('SomeClass'))-getReflecitonFileNamespace()-getAliases()

For PHP7 it can be extended more with AST parser information, for
example, add ReflectionSource class that can parse the source code and
build a reflection for that source. (new
ReflectionSource($fileContent))-getReflectionFileNamespaces()[0]-getAliases().
This patch will help a lot for tools that performs static analysis of
source code and provide a good API for userland extensions.

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Deprecated functions

2014-09-09 Thread Alexander Lisachenko
Hi!

Maybe it will be better to do this in another way: introduce an RFC to
add 'deprecated' keyword into the syntax like 'final' or 'protected'.
There are many frameworks that want to deprecate some methods or
classes. Currently it's only possible via @deprecated tag in the
phpDoc-block, but this tag doesn't influence on method invocation, so
no warnings are generated.

Symfony uses trigger_error($message, E_USER_DEPRECATED) explicitly in
deprecated methods to trigger this warning (see
https://github.com/symfony/symfony/pull/6180), but this is not a
transparent solution.

This can be look like this:

class Test {
deprecated protected $someProperty;

deprecated public function foo() {}
public function bar() {}
}


deprecated class OldStuff {}

deprecated function someOldFunction() {}

This RFC will give more control over 'deprecated' functionality and
can be easily tested.

Thoughts?

2014-09-10 9:42 GMT+04:00 Tjerk Meesters tjerk.meest...@gmail.com:
 Hi,

 When I was fixing test cases on my `kill-ereg` branch I noticed a Reflection 
 test case for `ReflectionFunction::isDeprecated()`.

 The problem with such a test case is that you’d be chasing deprecated 
 functions to tests against as we move along; this is the current list of 
 deprecated functions as taken from a typical 5.4 installation:

 Since 4.1.0: call_user_method, call_user_method_array
 Since 4.3.7: mysql_list_tables, mysql_listtables
 Since 5.3  : ereg, ereg_replace, eregi, eregi_replace, split, spliti, 
 sql_regcase, mysql_db_query, magic_quotes_runtime, set_magic_quotes_runtime, 
 set_socket_blocking
 Since 5.4  : mysql_list_dbs

 The above are, as far as I’m concerned, all potential candidates for removal 
 in PHP 7, so in order to reliably test a deprecated function I would suggest 
 introducing a hidden function with this signature:

 void __deprecated__() { }

 And mark that function as eternally deprecated using the ZEND_ACC_DEPRECATED 
 flag.

 Thoughts?

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php