NAME

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

SYNOPSIS

$EDITOR src

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.

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 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 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.

SEE ALSO

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