Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the PPI CPAN distribution.

Report information
The Basics
Id: 14868
Status: resolved
Priority: 0/
Queue: PPI

People
Owner: Nobody in particular
Requestors: thaljef [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 1.101
Fixed in: (no value)



Subject: value method for PPI::Token::Number
Adam- What do you think of a "value" method for Token::Number, which would remove the underscores, if there are any? sub value { my $value = $_[0]->content(); return eval $value; } Additionaly, you could overload Token::Number to DWIM in numeric contexts. $num = $doc->find_first('Token::Number'); print $num + 42; -Jeff
Date: Sat, 01 Oct 2005 22:02:42 +1000
From: Adam Kennedy <adam [...] phase-n.com>
To: bug-PPI [...] rt.cpan.org
Subject: Re: [cpan #14868] value method for PPI::Token::Number
RT-Send-Cc:
Let me briefly explain the API situation. PPI, as you are well aware, is an enormous fucking API. The problem I've found, and the reason why I've held back on a lot of these sorts of analysis methods, is that if you use a method name for say Token::Number, then it has a specific meaning and so it can't be reused in clashing classes. That means it can't be used in ::Token, or ::Node, or ::Element, or in anything else below ::Element where you may one day want to "push" the methods higher up the API towards ::Element from some lower subclass. For something with 50 classes, ALL of which I can think of two or three useful methods to have, it's a nightmare. Do I show all the very specific ones down under ->is_something? (my current preference). Do I just start assigning names and hope for the best (big doubts). What I think the best strategy might be is this. 1) For anything that can be seen as being general, pick a REALLY specific and general definition, and jam it all the way up as close to ::Element as possible, preferably IN element. If you don't have implementations of the method ready for all 50 classes, you ONLY document it in the ones that you have done it for, but treat the method as "marked for greatness" and assume it will get implement over the next few point releases. Or provide a useless default in ::Element... And then we combine those with extremely specific method names for the exotics so that there no risk stealing a potential name from a more global one. Get the idea? As for what you want, I suspect that it fits into my plan for ->literal. That is, you take a token, or a statement, or what have you, and IF that code is treated by perl itself as a literal value, then PPI will construct and return exactly that value. So you get the following. my $code = "{ foo => 'bar' }"; my $Document = PPI::Document->new( \$code ); is_deeply( $Document->child(0)->literal, { foo => 'bar' }, '->literal works as expected' ); The only tricky bit is error conditions... you either have to return EVERYTHING by reference and treat return undef as error, or you die on error. I'm not so fond of that, since I made a design decision to go with return undef on error, little to no list/wantarray returns, and to not use exceptions. But by-reference sucks ass, since you'd be calling ->literal for your children, unwrapping the references, building your thing, and then re-referencing it again, recursively :( So what we might do is define the "Literal" feature as a pair of methods. ->is_literal returns true/false on whether it is possible for an Element to be made literal, and then ->literal does the actual conversion, throwing a die/exception on failure. That way the only exceptions should be for people that don't read the manual and didn't do a ->is_literal first. And we don't owe those people very much. So... would ->literal (returning EXACTLY what Perl would otherwise see a number as) be sufficient for your need? The tricky bit is handling the weird number types without just getting pissed at how hard it is and just using string "eval". :) But then no string eval anywhere means no potential to even have code injection, and PPI's promise to never allow code injection is a core promise. Adam K Guest via RT wrote: Show quoted text
> This message about PPI was sent to you by guest <> via rt.cpan.org > > Full context and any attached attachments can be found at: > <URL: https://rt.cpan.org/Ticket/Display.html?id=14868 > > > Adam- > > What do you think of a "value" method for Token::Number, which would remove the underscores, if there are any? > > sub value { > my $value = $_[0]->content(); > return eval $value; > } > > Additionaly, you could overload Token::Number to DWIM in numeric contexts. > > $num = $doc->find_first('Token::Number'); > print $num + 42; > > -Jeff
From: thaljef [...] cpan.org
I understand what you're saying about managing method names and keeping things orthogonal as the API evolves. I think your "literal" method is a fine idea. For now, Perl::Critic has a perfectly adequate workaround. -Jeff [adam@phase-n.com - Sat Oct 1 08:03:38 2005]: Show quoted text
> Let me briefly explain the API situation. > > PPI, as you are well aware, is an enormous fucking API. > > The problem I've found, and the reason why I've held back on a lot of > these sorts of analysis methods, is that if you use a method name for > say Token::Number, then it has a specific meaning and so it can't be > reused in clashing classes. > > That means it can't be used in ::Token, or ::Node, or ::Element, or
in Show quoted text
> anything else below ::Element where you may one day want to "push"
the Show quoted text
> methods higher up the API towards ::Element from some lower subclass. > > For something with 50 classes, ALL of which I can think of two or > three > useful methods to have, it's a nightmare. Do I show all the very > specific ones down under ->is_something? (my current preference). > > Do I just start assigning names and hope for the best (big doubts). > > What I think the best strategy might be is this. > > 1) For anything that can be seen as being general, pick a REALLY > specific and general definition, and jam it all the way up as close
to Show quoted text
> ::Element as possible, preferably IN element. > > If you don't have implementations of the method ready for all 50 > classes, you ONLY document it in the ones that you have done it for, > but > treat the method as "marked for greatness" and assume it will get > implement over the next few point releases. Or provide a useless > default > in ::Element... > > And then we combine those with extremely specific method names for
the Show quoted text
> exotics so that there no risk stealing a potential name from a more > global one. > > Get the idea? > > As for what you want, I suspect that it fits into my plan for > ->literal. > > That is, you take a token, or a statement, or what have you, and IF > that > code is treated by perl itself as a literal value, then PPI will > construct and return exactly that value. > > So you get the following. > > my $code = "{ foo => 'bar' }"; > my $Document = PPI::Document->new( \$code ); > > is_deeply( $Document->child(0)->literal, { foo => 'bar' }, '->literal > works as expected' ); > > The only tricky bit is error conditions... you either have to return > EVERYTHING by reference and treat return undef as error, or you die
on Show quoted text
> error. I'm not so fond of that, since I made a design decision to go > with return undef on error, little to no list/wantarray returns, and > to > not use exceptions. > > But by-reference sucks ass, since you'd be calling ->literal for your > children, unwrapping the references, building your thing, and then > re-referencing it again, recursively :( > > So what we might do is define the "Literal" feature as a pair of > methods. ->is_literal returns true/false on whether it is possible
for Show quoted text
> an Element to be made literal, and then ->literal does the actual > conversion, throwing a die/exception on failure. > > That way the only exceptions should be for people that don't read the > manual and didn't do a ->is_literal first. And we don't owe those > people > very much. > > So... would ->literal (returning EXACTLY what Perl would otherwise
see Show quoted text
> a > number as) be sufficient for your need? > > The tricky bit is handling the weird number types without just
getting Show quoted text
> pissed at how hard it is and just using string "eval". :) > > But then no string eval anywhere means no potential to even have code > injection, and PPI's promise to never allow code injection is a core > promise. > > Adam K > > Guest via RT wrote:
> > This message about PPI was sent to you by guest <> via rt.cpan.org > > > > Full context and any attached attachments can be found at: > > <URL: https://rt.cpan.org/Ticket/Display.html?id=14868 > > > > > Adam- > > > > What do you think of a "value" method for Token::Number, which
would Show quoted text
> remove the underscores, if there are any?
> > > > sub value { > > my $value = $_[0]->content(); > > return eval $value; > > } > > > > Additionaly, you could overload Token::Number to DWIM in numeric
> contexts.
> > > > $num = $doc->find_first('Token::Number'); > > print $num + 42; > > > > -Jeff
On Sat Oct 01 03:29:33 2005, guest wrote: Show quoted text
> What do you think of a "value" method for Token::Number, which would > remove the underscores, if there are any?
This is now implemented in the PPI SVN revision 1167 as $token->literal() for PPI::Token::Number and subclasses. literal() will be propagated to other PPI::Token subclasses over time. -- Chris
Fixed in PPI 1.200