=head1 NAME

Pugs::Doc::Hack::Style - Style guidelines for Pugs code

=head1 SYNOPSIS

  $EDITOR src

=head1 DESCRIPTION

This document describes coding conventions used in Pugs code. Like any
style rules, these are meant as recommendations and you should feel free
to break them whenever it makes sense to do so.

=head2 Data types

Avoid punning data type names and data constructors. If you have code like:

  data Exp = Val Val | ...
  data Val = Int Int | String String | ...

Then readers your code may get confused about when you are using Val,
Int, and String as concrete types and when you are constructing a value.

The following convention is proposed. It can help against this problem,
and also deflect the namespace clashes that occur when two different
constructors from different types have the same name:

  data Exp
      = EVal     ExpVal     -- Variants use the first letter from "Exp"
      | EVar     ExpVar     -- Contained types chain the "Exp"
      ...

  data ExpVal               -- "Val" is the "given name" of "ExpVal"
      = VNative  ValNative  -- Use the given name's first letter in variants
      | VUndef   ValUndef   --     and the given name in grandchild types
      | VPure    ValPure
      | VMut     ValMut
      ...

   data ValMut              -- Exp > ExpVal > ValMut
      = MScalar  MutScalar
      | MArray   MutArray
      | MObject  MutObject
      ...

Since C<Val> is a common type not clearly a child only of Exp, it is
in fact defined as its own top-level type, and any type that uses it
defines an alias. So the above is really:

   data Val ...            -- As ExpVal above
   type ExpVal = Val       -- For use in Exp

Record types are also under convention keyed by dominating types, both
in constructor and in field names:

   -- Aliases always refer to toplevel name, so not "StorageVal" here
   type EntryStorage = TVar Val

   data PadEntry = MkEntry                   -- Single variant: Mk + given
      { e_declarator :: EntryDeclarator      -- Field name uses lowercase
      , e_storage    :: EntryStorage         --   first letter + underscore
      }

Multiple variant records drop the C<Mk> prefix and start with the
given name:

   type MutClass   = Class
   type ObjClass   = Class           -- Again, refer to toplevel directly

   type ObjId      = Native
   type ObjSlots   = TVar (Map Ident Val)
   type ObjPayload = Dynamic

   data MutObject                    -- Okay to abbreviate given name
      = ObjInstance                  --    when its nick is well-known
        { o_id       :: !ObjId
        , o_meta     :: !ObjClass
        , o_slots    :: !ObjSlots
        }
      | ObjForeign
        { o_id       :: !ObjId
        , o_meta     :: !ObjClass
        , o_payload  :: !ObjPayload
        }
      | ObjPrototype
        { o_id       :: !ObjId
        , o_meta     :: !ObjClass
        }

It is permissible to use a different prefix in non-shared field names,
using the variant name. So "oi_slots" and "of_opaque" are possible
alternate names for two of the fields above.

=head1 SEE ALSO

L<Perl6::Pugs>, L<Pugs::Doc::Hack>,
L<http://haskell.org/ghc/docs/latest/html/users_guide/>

