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/