deepseq-bounded-0.6.1.0: src/Control/DeepSeq/Bounded/Pattern.hs
-------------------------------------------------------------------------------
{- LANGUAGE CPP #-}
-------------------------------------------------------------------------------
-- |
-- Module : Control.DeepSeq.Bounded.Pattern
-- Copyright : Andrew G. Seniuk 2014-2015
-- License : BSD-style (see the file LICENSE)
--
-- Maintainer : Andrew Seniuk <rasfar@gmail.com>
-- Stability : provisional
-- Portability : portable
--
-------------------------------------------------------------------------------
-- (Warning is issued by Pattern_old_grammar.hs.)
--- #if ! NEW_IMPROVED_PATTERN_GRAMMAR
--- #warning You are using the old pattern grammar (NEW_IMPROVED_PATTERN_GRAMMAR flag is False). This will be deprecated in version 0.7.
--- #endif
module Control.DeepSeq.Bounded.Pattern
(
#if NEW_IMPROVED_PATTERN_GRAMMAR
-- * Pattern datatype
Pattern
, PatNode(..)
, PatNodeAttrs(..)
-- * Pattern DSL
-- | __Grammar__
--
-- @
-- /pat/ /->/ /[/ /modifiers/ /]/ /pat'/
-- /pat'/ /->/ __.__ /|/ __!__ /|/ __*__ /[/ /decimalint/ /]/ /|/ __(__ /{/ /pat/ /}/ __)__
-- /modifiers/ /->/ zero or one of each of the eight /modifier/, in any order
-- /modifier/ /->/ __=__ /|/ __+__ /|/ __^__ /|/ __\/__ /|/ __%__
-- /|/ __:__ /typename/ /{/ __;__ /typename/ /}/ __:__
-- /|/ __@__ /decimalint/
-- /|/ __>__ /permutation/
-- /typename/ /->/ string containing neither __:__ (unless /escaped/) nor __;__
-- /escaped/ /->/ __\\\\:__
-- /decimalint/ /->/ digit string not beginning with zero
-- /permutation/ /->/ of an initial part of the lowercase alphabet, /e.g./ __cdba__
-- @
--
-- Here is the grammar in a more <http://fremissant.net/deepseq-bounded/grammar.html#new-grammar vivid rendering>.
-- (Haddock makes it tricky to distinguish between metasyntax and concrete syntax.)
--
-- Optional whitespace can go between any two tokens (basically,
-- anyplace there is space shown in the grammar above).
--
-- Semicolons never need escaping, because they're already illegal
-- as part of any Haskell type name.
--
-- The semantics are given formally in the 'PatNode' and 'PatNodeAttrs'
-- documentation, as well as informally in the examples below and from
-- the project <http://www.fremissant.net/deepseq-bounded homepage>.
--
-- __Examples__
--
-- @\"__(...)__\"@ will match any ternary constructor.
--
-- @<http://hackage.haskell.org/package/deepseq-bounded-0.6.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html#t:NFDataP rnfp> \"__(!!!)__\" expr@ will force evaluation of @expr@ to a depth of two,
-- provided the head of @expr@ is a ternary constructor; otherwise it behaves
-- as @<http://hackage.haskell.org/package/deepseq-bounded-0.6.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html#t:NFDataP rnfp> \"__.__\" expr@ (/i.e./ do nothing).
--
-- @<http://hackage.haskell.org/package/deepseq-bounded-0.6.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html#t:NFDataP rnfp> \"__(...)__\" expr@ will force it to only a depth of one. That is,
-- @<http://hackage.haskell.org/package/deepseq-bounded-0.6.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html#t:NFDataP rnfp> \"__(...)__\" expr =
-- <http://hackage.haskell.org/package/deepseq-bounded-0.6.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html#t:NFDataP rnfp>
-- \"__!__\" expr@ when the head of @expr@
-- is a ternary constructor; otherwise it won't perform any evaluation.
--
-- @<http://hackage.haskell.org/package/deepseq-bounded-0.6.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html#t:NFDataP rnfp> \"__*__\" expr = <http://hackage.haskell.org/package/deepseq/docs/Control-DeepSeq.html#t:NFData rnf> expr@.
--
-- @<http://hackage.haskell.org/package/deepseq-bounded-0.6.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html#t:NFDataP rnfp> \"__(***)__\" expr@ will <http://hackage.haskell.org/package/deepseq/docs/Control-DeepSeq.html#t:NFData rnf> (deep) any ternary constructor, but
-- will not touch any constructor of other arity.
--
-- @<http://hackage.haskell.org/package/deepseq-bounded-0.6.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html#t:NFDataP rnfp> \"__(.(*.).)__\" expr@ will match any ternary constructor, then
-- match the second subexpression constructor if it is binary, and
-- if matching got this far, then the left sub-subexpression
-- will be forced (<http://hackage.haskell.org/package/deepseq/docs/Control-DeepSeq.html#t:NFData rnf>), but not the right.
--
-- @<http://hackage.haskell.org/package/deepseq-bounded-0.6.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html#t:NFDataP rnfp> \"__(!:T:*.)__\" expr@ will unwrap (shallow 'seq') the first
-- subexpression of @expr@, and the third subexpression won't be touched.
-- As for the second subexpression, if its type is @T@ it will be
-- completely evaluated (<http://hackage.haskell.org/package/deepseq/docs/Control-DeepSeq.html#t:NFData rnf>), but otherwise it won't be touched.
--
-- @<http://hackage.haskell.org/package/deepseq-bounded-0.6.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html#t:NFDataP rnfp> \"__(=**)__\" expr@ will spark the /parallel/ complete evaluation of
-- the two components of any pair. (Whether the computations actually
-- run in parallel depends on resource availability, and the discretion
-- of the RTS, as usual).
--
-- @<http://hackage.haskell.org/package/deepseq-bounded-0.6.0.0/docs/Control-DeepSeq-Bounded-NFDataP.html#t:NFDataP rnfp> \"__(>ba(+*+*)=*)__\" expr@ matches a binary constructor, whose first parameter is also a binary constructor. This identifies three main AST branches -- serendipitously symbolised by asterisks -- making up the expression: which branches we'll call __A__, __B__ and __C__. So this example will perform <http://hackage.haskell.org/package/deepseq/docs/Control-DeepSeq.html#t:NFData rnf>, but in a controlled manner: __A__ and __B__ are forced in parallel with __C__, and furthermore, __B__ is forced before __A__. A traceline will be printed at the beginning of the forcing of __B__ and then another traceline will be printed at the beginning of the forcing of __A__. Note that \"__(=>ba(+*+*)*)__\" would be a legal equivalent.
--
-- I make no claims as to the usefulness of the examples, they are here just to explain the semantics of the DSL.
--
-- __Details__
--
-- The present pattern parser ignores any subpatterns of all
-- pattern nodes except 'WR' and 'TR', optionally emitting a warning.
-- /(XXX In 0.6.0.0, I'm not sure the warning is still possible.)/
-- Hence, only 'WR' and 'TR' patterns are potentially recursive.
--
-- When specifying the list of subpatterns with 'WR' and 'TR',
-- in order for the match to succeed, the number of subpatterns must
-- be equal to the arity of the constructor the pattern node is
-- matching against. (No other pattern node types accept subpatterns.)
--
-- Additionally, in the case of 'TR', matching (and consequent recursion) will only
-- succeed if the term node has constructor name which is listed in the constraints.
--
-- It would be possible to have 'TR' nodes interpret the constraint
-- as type name rather than constructor name, but this would require /sum patterns/
-- (maybe for version 0.7). The problem is, no single 'WR' node
-- can match multiple constructors of differing arity. This has the
-- feel of an excellent application for SOP generics!...
--
-- (As contrasted with 'TR' nodes,) 'TI', 'TN' and 'TW' nodes interpret
-- type constraint strings as type names (not constructor names).
-- A moment's reflection will show you why it must be so.
--
-- Finally, if you're trying to name a constructor with __:__ in its name,
-- you must escape the colon with a backslash thus __\\\\:__ because
-- the unescaped colon is used as (opening and) closing character for
-- lists of type and constructor names.
{--}
-- Old interjection:
-- I regret that Haddock cannot offer better markup for distinguishing
-- the metasyntax. The bold is not bold enough. The alternation symbol,
-- although \/|\/ in the document comment, does not show as slanted for me.
-- Had no luck using color, also Unicode support seems pretty sketchy.
-- Embedding an image is possible via data URL, but this has been known
-- to crash Haddock except for very small images.
{--}
-- I'm still not sure if I try accepting a double-colon close here?
-- (Checking...)
-- /|/ /(/ __.__ /|/ __*__ /[/ /decimalint/ /]/ /)/ __::__ /typename/ /{/ __;__ /typename/ /}/ __:__ /[/ __:__ /]/
#if 0
-- These are now in Compile (but may move them back once sort out some stuff)
, compilePat
, showPat
#endif
, isWI , isWR , isWS , isWN , isWW , isTI , isTR , isTN , isTW
, emptyPatNodeAttrs
-- , emptySparkPatNodeAttrs
, getPatNodeAttrs
, setPatNodeAttrs
#if USE_PING_PATNODE
, setPatNodePingParentTID
#endif
, showPerm
, showPatRaw
, showPatNodeRaw
, setPatternPatNodeUniqueIDs
-- , patternShapeOK -- useful for defining instances of NFDataP
-- * Why depend on whole containers package, when we only want a rose tree
, Rose(..)
-- * Preferred to have this in Seqable, but had cyclical dependency issues
, SeqNode(..)
#else
-- * Pattern datatype
Pattern
, PatNode(..)
-- , patternShapeOK -- useful for defining instances of NFDataP
-- * Pattern DSL
-- | __Grammar__
--
-- @
-- /pat/ /->/ /[/ __=__ /]/ __.__ /[/ __{__ /{/ /pat/ /}/ __}__ /]/
-- /|/ /(/ /[/ __=__ /]/ __*__ /[/ /decimalint/ /]/ /|/ __#__ /)/
-- /|/ __.:__ /ctorname/ /{/ /space/ /ctorname/ /}/ __{__ /[/ /{/ /pat/ /}/ /]/ __}__
-- /|/ /(/ __*__ /[/ /decimalint/ /]/ /|/ __#__ /)/ __:__ /typename/ /{/ /space/ /typename/ /}/ __{}__
-- /typename/ -> /string/
-- /ctorname/ -> /string/
-- /decimalint/ -> /digit string not beginning with zero/
-- /space/ -> /space character ASCII 0x32/
-- @
--
-- Here is the grammar in a more <http://fremissant.net/deepseq-bounded/grammar.html vivid rendering>.
-- (The Haddock markup makes it almost tricky to distinguish between metasyntax and concrete syntax.)
--
-- __Examples__
--
-- @\".{...}\"@ will match any ternary constructor.
--
-- @'rnfp' \".{...}\" expr@ will force evaluation of @expr@ to a depth of two,
-- provided the head of @expr@ is a ternary constructor; otherwise it behaves
-- as @'rnfp' \"#\" expr@ (/i.e./ do nothing).
--
-- @'rnfp' \".{###}\" expr@ will force it to only a depth of one. That is,
-- @'rnfp' \".{###}\" expr = 'rnfp' \".\" expr@ when the head of @expr@
-- is a ternary constructor; otherwise it won't perform any evaluation.
--
-- @'rnfp' \"*\" expr = 'rnf' expr@.
--
-- @'rnfp' \".{***}\" expr@ will 'rnf' (deep) any ternary constructor, but
-- will not touch any constructor of other arity.
--
-- @'rnfp' \".{..{*.}.}\" expr@ will match any ternary constructor, then
-- match the second subexpression constructor if it is binary, and
-- if matching got this far, then the left sub-subexpression
-- will be forced ('rnf'), but not the right.
--
-- @'rnfp' \".{.*:T{}#}\" expr@ will unwrap (shallow 'seq') the first
-- subexpression of @expr@, and the third subexpression won't be touched.
-- As for the second subexpression, if its type is @T@ it will be
-- completely evaluated ('rnf'), but otherwise it won't be touched.
--
-- @'rnfp' \".{=**}\" expr@ will spark the /parallel/ complete evaluation of
-- the two components of any pair. (Whether the computations actually
-- run in parallel depends on resource availability, and the discretion
-- of the RTS, as usual).
--
-- __Details__
--
-- The present pattern parser ignores any subpatterns of all
-- pattern nodes except 'WR', 'TR' and 'PR', optionally emitting a warning.
-- Hence, only 'WR', 'TR' and 'PR' patterns are potentially recursive.
--
-- When specifying a list of subpatterns with 'WR' or 'PR',
-- in order for the match to succeed, the number of subpatterns must
-- be equal to the arity of the named constructor.
--
-- Type constraints must always be followed by __{__ (opening brace) as delimiter.
-- In the case of 'TR', if no recursion is desired, provide __{}__.
-- In order for the match to succeed, the number of subpatterns must either
-- be zero (__{}__), or be equal to the arity of the named constructor.
--
{--}
-- Old interjection:
-- I regret that Haddock cannot offer better markup for distinguishing
-- the metasyntax. The bold is not bold enough. The alternation symbol,
-- although \/|\/ in the document comment, does not show as slanted for me.
-- Had no luck using color, also Unicode support seems pretty sketchy.
-- Embedding an image is possible via data URL, but this has been known
-- to crash Haddock except for very small images.
#if 0
-- These are now in Compile (but may move them back once sort out some stuff)
, compilePat
, showPat
#endif
-- * Why depend on whole containers package, when we only want a rose tree
, Rose(..)
-- * Preferred to have this in Seqable, but had cyclical dependency issues
, SeqNode(..)
#endif
--- #if NEW_IMPROVED_PATTERN_GRAMMAR
--- module Control.DeepSeq.Bounded.Pattern_new_grammar ,
--- #else
--- module Control.DeepSeq.Bounded.Pattern_old_grammar ,
--- #endif
)
where
-------------------------------------------------------------------------------
#if NEW_IMPROVED_PATTERN_GRAMMAR
import Control.DeepSeq.Bounded.Pattern_new_grammar
#else
import Control.DeepSeq.Bounded.Pattern_old_grammar
#endif
-------------------------------------------------------------------------------