Categories
Posts in this category
- A shiny perl6.org site
- Creating an entry point for newcomers
- Sprixel, a 6 compiler powered by JavaScript
- Another perl6.org iteration
- Blackjack and Perl 6
- Why I commit Crud to the Perl 6 Test Suite
- Report from the Perl 6 Hackathon in Copenhagen
- Custom operators in Rakudo
- Defined Behaviour with Undefined Values
- Dissecting the "Starry obfu"
- Perl 6: Failing Softly with Unthrown Exceptions
- The first Perl 6 module on CPAN
- Google Summer of Code Mentor Recap
- Building a Huffman Tree With Rakudo
- Immutable Sigils and Context
- Is Perl 6 really Perl?
- Perl 6: Lost in Wonderland
- Lots of momentum in the Perl 6 community
- Musing and the future of feather and the Pugs repository
- Musings on Rakudo's spectest chart
- My first executable from Perl 6
- Trying to implement new operators - failed
- Let's build an object
- Perl 6 is optimized for fun
- How to get a parse tree for a Perl 6 Program
- Perl 6 in 2009
- Perl 6 ticket life cycle
- The Perl 6 Advent Calendar
- How to Plot a Segment of a Circle with SVG
- Publicity for Perl 6
- Rakudo architectural overview
- Rakudo Rocks
- Rakudo "star" announced
- Rakudo's rough edges
- Rats and other pets
- Releasing Rakudo made easy
- Set Phasers to Stun!
- Starry Perl 6 obfu
- Recent Perl 6 Developments August 2008
- Strings and Buffers
- Subroutines vs. Methods - Differences and Commonalities
- A SVG plotting adventure
- A Syntax Highlighter for Perl 6
- Test Suite Reorganization: How to move tests
- The Happiness of Design Convergence
- Perl 6 Tidings from September and October 2008
- Perl 6 Tidings for November 2008
- Perl 6 Tidings from December 2008
- Perl 6 Tidings from January 2009
- Perl 6 Tidings from February 2009
- Perl 6 Tidings from March 2009
- Perl 6 Tidings from April 2009
- Perl 6 Tidings from May 2009
- Perl 6 Tidings from May 2009 (second iteration)
- Perl 6 Tidings from June 2009
- Perl 6 Tidings from August 2009
- Perl 6 Tidings from October 2009
- Timeline for a syntax change in Perl 6
- Visualizing match trees
- We write a Perl 6 book for you
- When we reach 100% we did something wrong
- Where Rakudo Lives Now
- Why was the Perl 6 Advent Calendar such a Success?
- What you can write in Perl 6 today
- Why you don't need the Y combinator in Perl 6
Sun, 30 Aug 2009
Dissecting the "Starry obfu"
Permanent link
I've been asked a few times how the starry obfu works. Here it is again in all it's *cough* glory:
<(*+*)*(*+* +*/*) **** ** * * *+*+*/* **** ** * *
*+*-*/* **** ** * * *+* ****-* **** ** * * *-(*-*/
*) ** (*+*/*) **** ** * * *-* **** ** * * *-*+*/*
**** ** * * *+* **** ** * * *-* * * ***((* - */*)
** * * *-*/*) * * **** ** * * *+*/* ****-* ***(*-*
/*)**(*+*/*) * * ***((*-*/*)** * * *-*/*) * * ****
** * * *+*/* **** ** * * *+*+*/*-* * *>.split(<***
>).map: {eval("(* ** *+*+*-*/*+$_)(<* * *>)").chr\
.print}
This first character is a >, which introduces a list
quote: <a b c> is the same as ("a", "b", "c").
This quote covers the first six and three quarter of the sevenths line.
It is later then used a string (by calling .split on it, and
as such stringifies with spaces between the items. So it's roughly the same as
"..." in this context.
Then comes a fairly trivial part: the string is split on ***,
and via map a transformation is applied to to each item: it is
interpolated into a string, which is eval'ed. The result is taken as a Unicode
codepoint number, and printed to the screen.
To find out what exactly is evaled, you can replace the code inside the
map to read something like this:
<(*+*)*(*+* +*/*) **** ** * * *+*+*/* **** ** * *
...
>.map: { say("(* ** *+*+*-*/*+$_)(<* * *>)") };
The output begins with
(* ** *+*+*-*/*+(*+*)*(*+* +*/*) )(<* * *>) (* ** *+*+*-*/*+* ** * * *+*+*/* )(<* * *>)
You might ask yourself "how on earth is this valid Perl code?"
The answer is quite simple: a single star can be either a term or an operator in Perl 6. As an infix operator it is simply multiplication. As a term it does magic: It constructs a closure which takes one positional argument, and puts that everywhere where a * appears as a term within that expression.
The reason is to make things like @array[*-1] work: it creates
a closure { $_ - 1 } which is passed on to the array, which in
turn passes the number of items in that array to closure, making
@array[*-1] return the last array item.
So by the same token * ** *+*+*-*/*+(*+*)*(*+* +*/*) is
internally transformed to
{ $_ ** $_ + $_ + $_ - $_ / $_ + ($_ + $_ ) * ($_ + $_ + $_/ $_) }
The (<* * *>) behind it invokes that closure with a list
consisting of three items. In numerical context that becomes just the number
3, so the above translates to 3**3 + 3 + 3 - 3/3 + (3+3) * (3 + 3 +
3/3), evaluated 74 - the Unicode codepoint (and at the same time ASCII
code) for the letter capital J.
It works similarly for all other letters; mystery lifted.
Comments / Trackbacks:
Trackback URL:
/blog-en/perl-6/dissecting-starry-obfu.trackback
Write a comment
The comments on this blog post have been disabled; the comment form below will not work.