=head1 NAME

pugs::hack - How to hack on Pugs

=head1 SYNOPSIS

    # Fetch latest Pugs from Subversion repository
    $ svn co http://svn.openfoundry.org/pugs
    $ cd pugs

    # Configure Pugs
    $ perl Makefile.PL

    # Compile Pugs
    $ make

    # Test
    $ make test                            # or
    $ sudo cpan Bundle::Pugs::SmokeKit     # (once)
    $ make smoke                           # generates a smoke.html
    # Optionally, submit your smoke report to the public smokeserver:
    $ perl util/smokeserv/smokeserv-client.pl smoke.html

=head1 DESCRIPTION

This document attempts to explain how to start working on Pugs, as well as
conventions used in day-to-day development.

=head2 Source tree map

The Pugs source tree includes several major sections:

    .
    |-- LICENSE      Licenses that apply to the Pugs distribution
    |-- debian       Packaging rules for dpkg-based systems
    |-- docs         Documentation relating to Pugs/Perl 6/Haskell
    |-- examples     Examples of Perl 6 usage; many work in Pugs today
    |-- ext          Perl 6 modules that are installed with Pugs
    |-- inc          Perl 5 modules needed for build/test/install
    |-- lib          Perl 5 modules that are installed with Pugs
    |-- misc         Other modules, not directly used by Pugs
    |-- perl5        Internal Perl 5 modules for Pugs (compiler backends)
    |-- script       pugscc, the Pugs Compiler Collection
    |-- src          Source code for Pugs itself
    |-- t            Perl 6 test suite
    |-- t_disabled   Temporarily disabled tests
    `-- util         Utilities for hacking and testing Pugs

Expanding this one level deeper:

    .
    |-- LICENSE            Licenses that apply to the Pugs distribution
    |
    |-- debian             Packaging rules for dpkg-based systems
    |  |-- changelog           Changelog for Debian specific changes
    |  |-- compat              Sets debhelper compatibility version
    |  |-- control             File containing package definitions/dependencies
    |  |-- copyright           Debian copyright notice
    |  |-- patches             Debian specific patches
    |  |   |-- 00list          List of patches
    |  |   `-- 10smoker.dpatch Patch to djust smoker.yml path
    |  |-- pugs-doc.dirs       Directories to be created in the pugs-doc package
    |  |-- pugs-modules.dirs   Directories to be created in the pugs-modules
    |  |-- pugs-modules.install  Installation rules for the pugs-modules package
    |  |-- pugs-modules.lintian-overrides  Lintian overrides for pugs-modules
    |  |-- pugs.dirs           Directories to be created in the pugs package
    |  |-- pugs.docs           Documentation to be installed in the pugs package
    |  |-- pugs.install        Installation rules for the pugs package
    |  |-- pugs.links          List of links to be installed in the pugs package
    |  |-- rules               Makefile for building the Debian package
    |  `-- smoker.yml          Configuration file for smoke runs
    |
    |-- docs               Documentation relating to Pugs/Perl 6/Haskell
    |   |-- AES                Drafts of Perl6::Bible chapters
    |   |-- class              Object system sketches (XXXX: out of date?)
    |   |-- notes              Misc design notes and musings
    |   |-- other              Misc tips to day-to-day development
    |   |-- quickref           Perl 6 quick reference pages
    |   |-- src                Junction implementation sketch (XXXX: ood?)
    |   |-- talks              Slides for Pugs and Perl 6 talks
    |   |-- zh-cn              Simplified Chinese doc translations
    |   `-- zh-tw              Traditional Chinese doc translations
    |
    |-- examples           Examples of Perl 6 usage; many work in Pugs today
    |   |-- advocacy           Pugs/Perl 6-advocacy MOTD generator
    |   |-- algorithms         Basic algorithms
    |   |-- cgi                CGI scripts and applications
    |   |-- continuation       Fun with continuations
    |   |-- cookbook           Perl 6 idiomatic Perl Cookbook
    |   |-- functional         Functional programming concepts
    |   |-- games              Playable games
    |   |-- golf               Minimal (key)stroke puzzle solutions
    |   |-- hashes             Use of Perl 6 hashes
    |   |-- japh               JAPHs using various idioms
    |   |-- junctions          Fun with junctions
    |   |-- naive_bayesian     Naive Bayesian Text Classification
    |   |-- nested_loops       Many ways to do runtime nested loops
    |   |-- network            Networking clients, servers, bots, etc.
    |   |-- obfu               Obfuscated code and obfuscation techniques
    |   |-- output             Expected example outputs, for testing
    |   |-- p6explain          Incomplete tool which explains Perl 6 constructs
    |   |-- perl5              Programs that use Perl 5 modules
    |   |-- poetry             Perl 6 poetry
    |   |-- ppt                Perl 6 Power Tools, ports of *nix userland
    |   |-- qotw               Perl 6 solutions to plover's Quiz Of The Week
    |   |-- slurpy-list-parms  Use of Perl 6 slurpy lists (XXXX: -> t/?)
    |   |-- tutorial_gen       Tutorial generator (XXXX: huh?)
    |   `-- vmethods           Add virtual methods to existing types
    |
    |-- ext                Perl 6 modules that are installed with Pugs
    |   |-- Algorithm-TokenBucket  Token bucket rate limiting
    |   |-- Benchmark          Benchmark runtime of Perl 6 code
    |   |-- CGI                CGI author's helper module
    |   |-- Config-Tiny        Pre-Pugs-OO .ini file reader
    |   |-- DateTime           Port of Perl 5 DateTime, with API changes
    |   |-- DateTime-Set       Port of Perl 5 DateTime::Set/Span/SpanSet
    |   |-- FA-DFA             Simple Deterministic Finite Automata
    |   |-- File-Find          Traverse a directory tree
    |   |-- File-Spec          Portable File handling
    |   |-- FindBin            Find directory of Perl script
    |   |-- HTML-Entities      Encode/decode HTML entities
    |   |-- HTTP-Server-Simple Base class for simple CGI-capable HTTP servers
    |   |-- Kwid-Event-Parser  Event-based API (like XML SAX) for Kwid
    |   |-- MIME-Base64        Base64 encode/decode (not a Perl 5 port)
    |   |-- Module-Pluggable-Fast  Find and load plugin modules
    |   |-- Net-IRC            IRC protocol implementation
    |   |-- Perl-Compiler      A Perl 6 port of Pugs
    |   |-- Perl6-Container-Array  Perl 6 implementation of Perl 6 lazy arrays
    |   |-- Perl6-Value-List   Perl 6 implementation of Perl 6 lazy lists
    |   |-- Perldoc            Event-based API for Perldoc DOM
    |   |-- Pod-Event-Parser   Event-based API (like XML SAX) for POD
    |   |-- Recurrence         Recurrence operations
    |   |-- Rosetta-Incubator  Rigorous Database Portability
    |   |-- Set                Set calculus operations
    |   |-- Set-Infinite       Infinite set operations
    |   |-- Span               Span operations
    |   |-- Test               Testing support library
    |   |-- Test-Builder       Backend for building test libraries
    |   |-- Text-Glob          Translate glob to regex
    |   |-- Tree               Basic n-ary tree data structure
    |   |-- URI                Escape/unescape URI strings
    |   |-- WTemplate          Widget-based templating engine
    |   |-- fp                 Functional programming operators
    |   |-- lib                Pragma to add paths to @*INC
    |   `-- libwww-perl        Port of Perl 5 libwww-perl modules
    |
    |-- inc                Perl 5 modules needed for build/test/install
    |   |-- Module             Module::Install
    |   |-- PugsBuild          Support modules for config.yml make controls
    |   `-- Test               Test::Harness
    |
    |-- lib                Pugs- and Perl 6-related Perl 5 modules
    |   |-- Inline             Inline::Pugs
    |   |-- Perl6              Perl6::MakeMaker, Perl6::Pugs
    |   `-- pugs               POD docs for Pugs itself
    |
    |-- misc               Other modules, not directly used by Pugs
    |   |-- Blondie            Intermediate language and compiler collection
    |   |                      used to demonstrate a possible approach to
    |   |                      compilation
    |   |-- Class-Events       Redesign of Perl 5's Class::Publisher
    |   |-- Date               Date/calendar calculations
    |   |-- Grammars           Perl 6 grammar written as Perl 6 rules
    |   |-- JavaScript-FrontEnd  JavaScript Frontend
    |   |-- org.perl6.metamodel  Prototype Perl 6 metaclass model: Java
    |   |-- Perl-MetaModel     Prototype Perl 6 metaclass model: Perl 5,
    |   |                      version 1.0
    |   |-- POE                Beginning of an experimental port of Perl 5 POE
    |   |-- T2-Perl6           T2 (Tangram::Schema redesign) -> Perl6::Class 
    |   |-- XML-Sax            Simple API for XML
    |
    |-- perl5              Internal Perl 5 modules for Pugs (compiler backends)
    |   |-- Perl6-Container    Perl 6 containers implemented using the Perl 5
    |   |                      metamodel
    |   |-- Perl6-MetaModel    Prototype Perl 6 metaclass model: Perl 5,
    |   |                      version 2.0
    |   |-- Perl6-Value        Perl 6 values implemented using the Perl 5
    |   |                      metamodel
    |   |-- PIL-Run            PIL virtual machine in Perl 5
    |   `-- PIL2JS             PIL to JavaScript compiler
    |
    |-- script             pugscc, the Pugs Compiler Collection
    |
    |-- src                Haskell source for pugs itself
    |   |-- Data               Syck-based YAML parser
    |   |-- Emit               Parrot PIR backend
    |   |-- PIL                PIL2 implementation
    |   |-- Pugs               Core Pugs engine
    |   |-- RRegex             PCRE-based regular expressions support
    |   |-- pcre               Import of PCRE source
    |   |-- perl5              Perl 5 bidirectional call support
    |   |-- perl6              The Perl 6 prelude (definition of builtins)
    |   |-- pge                Import of PGE (Parrot Grammer Engine) source
    |   `-- syck               Import of Syck source
    |
    |-- t                  Pugs/Perl 6 test library
    |   |-- 01-sanity          Sanity checks that testing can proceed
    |   |-- Synopsis           Pointers to online AES docs and tests
    |   |-- Test-Less          Test index for test-less utility
    |   |-- builtins           Builtin function tests
    |   |-- data_types         Basic data type tests
    |   |-- examples           Make examples/ tree act as tests
    |   |-- general            Miscellaneous tests
    |   |-- junction           Junction tests
    |   |-- macros             Macro tests
    |   |-- magicals           Magical variable tests
    |   |-- oo                 Object Oriented programming tests
    |   |-- operators          Operator tests
    |   |-- packages           Tests for packages
    |   |-- pugsbugs           Uncategorized tests for known broken behavior
    |   |-- pugsrun            Tests for pugs (as opposed to Perl 6)
    |   |-- rules              Perl 6 rule and Perl 5 regex tests
    |   |-- statements         Statement-level construct tests
    |   |-- subroutines        Block/Code/Sub/etc. tests
    |   |-- syntax             Basic syntax tests
    |   |-- types              Tests for types
    |   |-- unspecced          Tests for Pugs extensions to Perl 6
    |   `-- var                Variable declaration tests
    |
    |-- t_disabled         Disabled tests
    |   |-- Dialects           Perl 6 non-standard dialects
    |   |-- builtins           Problems with system() and strings with spaces
    |   `-- rules              Port of tests from CPAN module Perl6::Rules
    |
    `-- util               Utilities for hacking and testing Pugs
        `-- livecd             Tool to create a minimalistic Pugs Live CD

=head2 Subversion properties

If you add a new text file (e.g. a test, a C<.pm>, etc.) to the repository,
please use C<util/add-svn-props.sh> to add standard Subversion properties to
your new file:

    $ ./util/add-svn-props.sh newfile1 newfile2

If you're on Win32 and can't run shell scripts, run C<svn> manually:

    $ svn propset svn:eol-style "native" newfile1 newfile2
    $ svn propset svn:mime-type "text/plain; charset=UTF-8" newfile1 newfile2

If you create a new subdirectory under C<ext/>, please remember to set the
C<svn:ignore> property to tell Subversion to ignore automatically generated
files like C<Makefile> or C<blib/>.

    $ cat > /tmp/props
    pm_to_blib
    blibdirs
    Makefile
    Makefile.old
    blib
    $ svn propset svn:ignore -F /tmp/props ext/Your-New-Module

Except for the files in F<script/> and F<util/>, C<svn:executable> should
always be unset, even for test files.

=head2 Shebang lines

All test files should use C<#!/usr/bin/pugs> as the shebang line (first line of
the script). There're no real technical reasons for this convention, it's just
for consistency. Remember to put a C<use v6> in the beginning of your Perl 6
programs, too, to keep perl5 from accidentally running Perl 6 code.

=head2 Naming conventions

=over

=item *

"Perl 6" is the name of the programming language and the project, while "perl6"
is the name of the Perl 6 compiler/interpreter.

=item *

"Pugs" is the name of the Pugs project, while "pugs" is the name of the binary
C<pugs>, i.e. the compiler/interpreter.

=item *

"Perl 5" is the name of the programming language and the project, while "perl5"
is the name of the Perl 5 interpreter.

=back

=head2 Editing

There is a F<util/perl6.vim> Vim syntax file.  There is an
F<util/cperl6-mode.el> Emacs mode. If you don't use it, then perl-mode
works better than cperl-mode.

Where applicable, conventions documented in Damian Conway's "Perl Best
Practices" book (O'Reilly, 2005) should be followed by default.  At the very
least, all indenting should be done with spaces (4 per indent level) rather than
tabs, so the code and documentation looks the same to everyone.

If you use Vim, you may want to set the following settings:

    set shiftwidth=4 autoindent expandtab smarttab softtabstop=1

This will cause Vim to insert four spaces instead of a real tab upon pressing
C<< <Tab> >>.  The equivalent settings for Emacs are:

    c-indentation-style: bsd
    c-basic-offset: 4
    indent-tabs-mode: nil

If you use Emacs with cperl6-mode, you can set these code conventions
in your config file with:

     (add-hook 'cperl6-mode-hook
               '(lambda () (cperl6-set-style "Pugs")))

If you use BBEdit, you can configure it to auto-expand tabs like this:

=over

=item 0.

Launch the BBEdit application.

=item 1.

In the 'BBEdit' (application) menu, choose 'Preferences'.

=item 2.

In the resulting dialog box, choose 'Editor Defaults' from the left col.

=item 3.

In the resulting panel, ensure 'Auto-Expand Tabs' is checked.

=item 4.

Also ensure the 'Default Font' is set to '4 spaces per tab'.

=item 5.

Close the dialog box.

=back

These exact settings apply to BBEdit 8, the newest version; older versions of
the program may store the same configuration options elsewhere.

=head2 Testing

See L<pugs::run> and F<t/README>.  If you wish to use the C<prove> utility
to run individual tests or test directories, you will need to set at least
the following environment variables first:

    $ export HARNESS_PERL=./pugs
    $ export PERL6LIB=blib6/lib

You can also just say C<./pugs -Iblib6/lib t/.../mumble.t>.

=head3 Regex testing

Using the Parrot distribution, PGE can be tested interactively with

    $ ./parrot compilers/pge/demo.pir

and with tests like those in F<t/p6rules/>.

Using the PCRE distribution, PCRE can be tested interactively with

    $ ./pcretest

=head2 Resources

=over

=item L<http://www-users.cs.york.ac.uk/~ndm/hoogle/>

A cross index of standard Haskell libraries.  It is searchable by type
signature, name, etc.

=item L<http://rt.openfoundry.org/Foundry/Project/Source/index.html/pugs/browse/>

Browsable Pugs VCS.  You sometimes get a blank page the first time you access a
URL (a timeout) - just click again.

=item L<http://svn.perl.org/perl6/pugs/trunk/>

Mirror of Pugs VCS head.  Usually faster and more reliable than the OpenFoundry
browser, but doesn't show diffs between revisions.

=item L<http://m19s28.vlinux.de/cgi-bin/pugs-smokeserv.pl>

Pugs Smoke Reports Server.  List of recently uploaded smoke reports sorted by
the runcore used (normal Haskell backend, PIL2JS, PIL-Run, PIR, etc.), see
F<util/smokeserv/README> for more information.

=back

=head1 SEE ALSO

L<Perl6::Pugs>, L<pugs::run>
