The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
=head1 NAME

Language::GolfScript - Perl implementation of GolfScript 

=head1 VERSION

Version 0.04

=head1 SYNOPSIS

    # 1000 digits of PI, see http://golfscript.com/golfscript/examples.html
    use Language::GolfScript;
    Language::GolfScript::run(q#;''
    6666,-2%{2+.2/@*\/10.3??2*+}*#);

    # command-line. Say ...
    $ perl -MG myscript.gs
    # ... instead of ...
    $ ruby golfscript.rb myscript.gs
    # look! you already saved 10 keystrokes!

    # one-liner to compute pow(4,24)
    $ perl -MG -e '4 24?'
    281474976710656

=head1 DESCRIPTION

(From L<http://www.golfscript.com/golfscript/index.html>)

GolfScript is a stack oriented esoteric programming language
aimed at solving problems (B<holes>) in as few keyB<strokes>
as possible. It also aims to be simple and easy to write.

Short code is achieved by using single symbols to represent 
high level operations (such as map, join, array size, etc). 
Being stack based allows for functions and other manipulations 
to work without the need for explicit variables, however 
variables still exist and are useful for more complicated 
stack manipulations.

More details about GolfScript, including documentation,
a tutorial, and examples are available at the home page

    http://www.golfscript.com/golfscript/

The C<Language::GolfScript> module is a Perl implementation 
of the GolfScript spec, which was originally written in Ruby.
It includes the C<G> package, which simply wraps a source
filter around C<Language::GolfScript> and allows a GolfScript
source file to be executed from the command line.

The current implementation is ~2100 lines and is still missing
a few features. But I'm going to see if I can get it even lower! ;-)

=head1 FUNCTIONS

Mainly the C<G> package uses source filtering to automatically
parse and execute the contents of a source file as GolfScript.
But it makes use of the following functions in the
C<Language::GolfScript> module, which may also be
called independently (to debug or to try several test cases,
for example).

=head2 Execution methods

=over 4

=item C< Language::GolfScript::run($source_string) >

Initializes the GolfScript interpreter, executes the specified
string of GolfScript code, and prints
the resulting stack to standard output.

=item C< Language::GolfScript::test($source_string [, $input) >

Initializes the stack to the specified input, executes the
specified string of GolfScript code, and returns a string
represnting the output of the GolfScript program.

=item C< Language::GolfScript::evaluate($source_string) >

Evaluates a string of GolfScript code with respect
to the current stack. May change the stack depending
on the code that was executed.

=cut

To document:   gspush, gspop, gsoutput

gspush to_string($string);
gspush to_block($golfscript_block);
gspush to_number($number);
gspush [ to_<type>($element1), to_<type>($element2), ... ];

$element = gspop();
if (is_string($element)) { $string = get_string($element) }
elsif (is_block($element)) { $block = get_block($element) }
elsif (is_number($element)) { $number = get_number($element) }
elsif (is_array($element)) { @array = @$element }

=back

=head1 VARIABLES

=over 4

=item C<Language::GolfScript::INPUT>

Input to the GolfScript program. When the module is first loaded,
this variable is initialized from standard input and the stack
is set to contain a single string containing this input.

=item C<Language::GolfScript::DEBUG>

If set to one, this module will write many details about
the operations being performed to standard error.

If set to a value greater than one, this module will write
even more details about operation of the GolfScript parser.

Any of these constructions

    use Language::GolfScript 'debug';
    use G 'debug';
    $ perl -MG=debug myscript.gs

will initialize C<Language::GolfScript::DEBUG> to C<1>. Using the
word C<verbose> instead of C<debug> will initialize
C<Language::GolfScript::DEBUG> to 2.


=item C<Language::GolfScript::COUNT>

If set to non-zero, reports the character count to
standard output after the script is evaluated.

This variable may be initialized to 1 by passing the word
C<count> to the module's import function, for example like

    use Language::GolfScript 'count'
    $ perl -MG=debug,count myscript.gs

The code length count function attempts to remove comments
and whitespace that "looks" unnecessary. If any tokens were
removed from the code for the counting function, the function
will also display the "stripped" code. In this way, you may
develop a script that includes comments and commented-out
sections of code, and get a string of code where most of
the unnecessary characters have already been removed.

=item C<Language::GolfScript::TIMEOUT>

If non-zero, terminates the program after the specified
number of seconds. Helpful if your GolfScript code might
enter an infinite loop.

This variable can be initialized by passing the word
C<timeout> to the module's import function.

    use Language::GolfScript timeout => 60;
    $ perl -MG=timeout=10 myscript.gs

=back

=head1 EXPORTS

None

=head1 DISCREPANCIES BETWEEN RUBY/PERL GOLFSCRIPT IMPLEMENTATIONS

While much effort has been devoted to getting the Perl implementation
of GolfScript to conform to the specification and to be consistent
with the Ruby implementation, there are a few differences.

=over 4

=item Perl implementation is not complete

Every effort has been made to get the specific examples
on the GolfScript Builtins page 
L<http://golfscript.com/golfscript/builtin.html> to work.
But the implementation may have neglected some
infrequently used operations that are valid GolfScript
syntax (say, the C<)> operating on a block). 
Feel free to bring these edge cases to
my attention with CPAN's Request Tracker (see
L<"SUPPORT AND DOCUMENTATION">, below).

=item Perl GolfScript is slow

Supposedly, Ruby is slow and the Ruby GolfScript implementation
is even L<slower|http://www.golfscript.com/golfscript/syntax.html>.
Well, Perl GolfScript is slower still, for a variety of reasons.

If biginteger operations are particularly painful on your script,
consider installing C<libgmp> (L<http://gmplib.org/>) on your
system along with the L<Math::BigInt::GMP> package.

=item Interpolated string parsing

Ruby's string parsing function allows arbitrary Ruby expressions
to be included in strings with the C<#{ruby expression}> syntax.
This functionality is also exported to Ruby GolfScript:

    "The time is now #{Time.now}"

In Perl's GolfScript, the best we can easily do is to evaluate
this syntax as a Perl expression with Perl's C<eval> function.
So an equivalent Perl GolfScript code snippet would be

    "The time is now #{scalar localtime}"

=item Error messages

Illegal operations in GolfScript generate a stack trace.
The Ruby and Perl GolfScript stack traces will necessarily
look different for the same error.

=back

=head1 SUPPORT AND DOCUMENTATION

After installing, you can find documentation for this module with the
perldoc command.

    perldoc Language::GolfScript

You can also look for information at:

    RT, CPAN's request tracker
        http://rt.cpan.org/NoAuth/Bugs.html?Dist=Language-GolfScript

    AnnoCPAN, Annotated CPAN documentation
        http://annocpan.org/dist/Language-GolfScript

    CPAN Ratings
        http://cpanratings.perl.org/d/Language-GolfScript

    Search CPAN
        http://search.cpan.org/dist/Language-GolfScript/

=head1 AUTHOR

Specification and original Ruby implementation by Darren Smith.

Perl implementation by Marty O'Brien, E<lt>mob@cpan.orgE<gt>.

=head1 COPYRIGHT

Copyright (c) 2010, Marty O'Brien

This library is free software; you can redistribute it and/or
modify it under the same terms as Perl itself, either Perl
version 5.12.0 or, at your option, any later version of
Perl 5.

=cut