diff options
author | Takano Akio <tak@anoak.io> | 2018-01-31 21:35:29 -0500 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2018-01-31 23:28:48 -0500 |
commit | be84823b956f0aa09c58d94d1901f2dff13546b4 (patch) | |
tree | 94b76f4746a8af6748bbfb2f868c9fd98206735f /docs | |
parent | 0bff9e677f0569bc8a7207c20cddddfd67e2448f (diff) | |
download | haskell-be84823b956f0aa09c58d94d1901f2dff13546b4.tar.gz |
Implement BlockArguments (#10843)
This patch implements the BlockArguments extension, as proposed at
https://github.com/ghc-proposals/ghc-proposals/pull/90. It also
fixes #10855 as a side-effect.
This patch adds a large number of shift-reduce conflicts to the parser.
All of them concern the ambiguity as to where constructs like `if` and
`let` end. Fortunately they are resolved correctly by preferring shift.
The patch is based on @gibiansky's ArgumentDo implementation (D1219).
Test Plan: ./validate
Reviewers: goldfire, bgamari, alanz, mpickering
Reviewed By: bgamari, mpickering
Subscribers: Wizek, dfeuer, gibiansky, rwbarton, thomie, mpickering, carter
GHC Trac Issues: #10843, #10855
Differential Revision: https://phabricator.haskell.org/D4260
Diffstat (limited to 'docs')
-rw-r--r-- | docs/users_guide/bugs.rst | 6 | ||||
-rw-r--r-- | docs/users_guide/glasgow_exts.rst | 98 |
2 files changed, 98 insertions, 6 deletions
diff --git a/docs/users_guide/bugs.rst b/docs/users_guide/bugs.rst index 7d41d874bb..3cfc023ea0 100644 --- a/docs/users_guide/bugs.rst +++ b/docs/users_guide/bugs.rst @@ -83,12 +83,6 @@ Context-free syntax (let x = 42 in x == 42 == True) -- The Haskell Report allows you to put a unary ``-`` preceding certain - expressions headed by keywords, allowing constructs like ``- case x of ...`` - or ``- do { ... }``. GHC does not allow this. Instead, unary ``-`` is allowed - before only expressions that could potentially be applied as a function. - - .. _infelicities-exprs-pats: Expressions and patterns diff --git a/docs/users_guide/glasgow_exts.rst b/docs/users_guide/glasgow_exts.rst index 514dae8dd6..190c611ede 100644 --- a/docs/users_guide/glasgow_exts.rst +++ b/docs/users_guide/glasgow_exts.rst @@ -2098,6 +2098,104 @@ data constructor in an import or export list with the keyword ``pattern``, to allow the import or export of a data constructor without its parent type constructor (see :ref:`patsyn-impexp`). +.. _block-arguments: + +More liberal syntax for function arguments +------------------------------------------ + +.. extension:: BlockArguments + :shortdesc: Allow ``do`` blocks and other constructs as function arguments. + + :since: 8.6.1 + + Allow ``do`` expressions, lambda expressions, etc. to be directly used as + a function argument. + +In Haskell 2010, certain kinds of expressions can be used without parentheses +as an argument to an operator, but not as an argument to a function. +They include ``do``, lambda, ``if``, ``case``, and ``let`` +expressions. Some GHC extensions also define language constructs of this type: +``mdo`` (:ref:`recursive-do-notation`), ``\case`` (:ref:`lambda-case`), and +``proc`` (:ref:`arrow-notation`). + +The :extension:`BlockArguments` extension allows these constructs to be directly +used as a function argument. For example:: + + when (x > 0) do + print x + exitFailure + +will be parsed as:: + + when (x > 0) (do + print x + exitFailure) + +and + +:: + + withForeignPtr fptr \ptr -> c_memcpy buf ptr size + +will be parsed as:: + + withForeignPtr fptr (\ptr -> c_memcpy buf ptr size) + +Changes to the grammar +~~~~~~~~~~~~~~~~~~~~~~ + +The Haskell report `defines +<https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-220003>`_ +the ``lexp`` nonterminal thus (``*`` indicates a rule of interest):: + + lexp → \ apat1 … apatn -> exp (lambda abstraction, n ≥ 1) * + | let decls in exp (let expression) * + | if exp [;] then exp [;] else exp (conditional) * + | case exp of { alts } (case expression) * + | do { stmts } (do expression) * + | fexp + + fexp → [fexp] aexp (function application) + + aexp → qvar (variable) + | gcon (general constructor) + | literal + | ( exp ) (parenthesized expression) + | qcon { fbind1 … fbindn } (labeled construction) + | aexp { fbind1 … fbindn } (labelled update) + | … + +The :extension:`BlockArguments` extension moves these production rules under +``aexp``:: + + lexp → fexp + + fexp → [fexp] aexp (function application) + + aexp → qvar (variable) + | gcon (general constructor) + | literal + | ( exp ) (parenthesized expression) + | qcon { fbind1 … fbindn } (labeled construction) + | aexp { fbind1 … fbindn } (labelled update) + | \ apat1 … apatn -> exp (lambda abstraction, n ≥ 1) * + | let decls in exp (let expression) * + | if exp [;] then exp [;] else exp (conditional) * + | case exp of { alts } (case expression) * + | do { stmts } (do expression) * + | … + +Now the ``lexp`` nonterminal is redundant and can be dropped from the grammar. + +Note that this change relies on an existing meta-rule to resolve ambiguities: + + The grammar is ambiguous regarding the extent of lambda abstractions, let + expressions, and conditionals. The ambiguity is resolved by the meta-rule + that each of these constructs extends as far to the right as possible. + +For example, ``f \a -> a b`` will be parsed as ``f (\a -> a b)``, not as ``f +(\a -> a) b``. + .. _syntax-stolen: Summary of stolen syntax |