Introduce operator aliases by garyb · Pull Request #1691 · purescript/purescript · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
7 changes: 7 additions & 0 deletions examples/failing/OperatorAliasNoExport.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- @shouldFailWith TransitiveExportError
module Test ((?!)) where

infixl 4 what as ?!

what :: forall a b. a -> b -> a
what a _ = a
11 changes: 11 additions & 0 deletions examples/passing/OperatorAlias.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Main where

import Prelude
import Control.Monad.Eff.Console

infixl 4 what as ?!

what :: forall a b. a -> b -> a
what a _ = a

main = log $ "Done" ?! true
6 changes: 4 additions & 2 deletions purescript.cabal
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: purescript
version: 0.7.6.1
version: 0.8.0.0
cabal-version: >=1.8
build-type: Simple
license: MIT
Expand Down Expand Up @@ -261,10 +261,12 @@ test-suite tests
build-depends: base >=4 && <5, containers -any, directory -any,
filepath -any, mtl -any, parsec -any, purescript -any,
transformers -any, process -any, transformers-compat -any, time -any,
Glob -any, base-compat >=0.6.0
Glob -any, aeson-better-errors -any, bytestring -any, aeson -any,
base-compat -any
type: exitcode-stdio-1.0
main-is: Main.hs
other-modules: TestsSetup
TestPscPublish
buildable: True
hs-source-dirs: tests tests/common

Expand Down
4 changes: 2 additions & 2 deletions src/Language/PureScript/AST/Declarations.hs
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,9 @@ data Declaration
--
| ExternDataDeclaration ProperName Kind
-- |
-- A fixity declaration (fixity data, operator name)
-- A fixity declaration (fixity data, operator name, value the operator is an alias for)
--
| FixityDeclaration Fixity String
| FixityDeclaration Fixity String (Maybe Ident)
-- |
-- A module import (module name, qualified/unqualified/hiding, optional "qualified as" name)
-- TODO: also a boolean specifying whether the old `qualified` syntax was used, so a warning can be raised in desugaring (remove for 0.9)
Expand Down
2 changes: 1 addition & 1 deletion src/Language/PureScript/AST/Exported.hs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ isExported (Just exps) decl = any (matches decl) exps
matches (TypeDeclaration ident _) (ValueRef ident') = ident == ident'
matches (ValueDeclaration ident _ _ _) (ValueRef ident') = ident == ident'
matches (ExternDeclaration ident _) (ValueRef ident') = ident == ident'
matches (FixityDeclaration _ name) (ValueRef ident') = name == runIdent ident'
matches (FixityDeclaration _ name _) (ValueRef ident') = name == runIdent ident'
matches (DataDeclaration _ ident _ _) (TypeRef ident' _) = ident == ident'
matches (ExternDataDeclaration ident _) (TypeRef ident' _) = ident == ident'
matches (TypeSynonymDeclaration ident _ _) (TypeRef ident' _) = ident == ident'
Expand Down
17 changes: 3 additions & 14 deletions src/Language/PureScript/CoreFn/Desugar.hs
Original file line number Diff line number Diff line change
@@ -1,17 +1,3 @@
-----------------------------------------------------------------------------
--
-- Module : Language.PureScript.CoreFn.Desugar
-- Copyright : (c) 2013-15 Phil Freeman, (c) 2014-15 Gary Burgess
-- License : MIT (http://opensource.org/licenses/MIT)
--
-- Maintainer : Phil Freeman <paf31@cantab.net>, Gary Burgess <gary.burgess@gmail.com>
-- Stability : experimental
-- Portability :
--
-- | The AST -> CoreFn desugaring step
--
-----------------------------------------------------------------------------

module Language.PureScript.CoreFn.Desugar (moduleToCoreFn) where

import Data.Function (on)
Expand Down Expand Up @@ -68,6 +54,9 @@ moduleToCoreFn env (A.Module _ coms mn decls (Just exps)) =
declToCoreFn ss _ (A.DataBindingGroupDeclaration ds) = concatMap (declToCoreFn ss []) ds
declToCoreFn ss com (A.ValueDeclaration name _ _ (Right e)) =
[NonRec name (exprToCoreFn ss com Nothing e)]
declToCoreFn ss com (A.FixityDeclaration _ name (Just alias)) =
let qname = Qualified (Just mn) alias
in [NonRec (Op name) (Var (ss, com, Nothing, getValueMeta qname) (Qualified Nothing alias))]
declToCoreFn ss _ (A.BindingGroupDeclaration ds) =
[Rec $ map (\(name, _, e) -> (name, exprToCoreFn ss [] Nothing e)) ds]
declToCoreFn ss com (A.TypeClassDeclaration name _ supers members) =
Expand Down
8 changes: 5 additions & 3 deletions src/Language/PureScript/Docs/AsMarkdown.hs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ declAsMarkdown decl@Declaration{..} = do
zipWithM_ (\f c -> tell' (childToString f c)) (First : repeat NotFirst) children
spacer

for_ declFixity (\fixity -> fixityAsMarkdown fixity >> spacer)
for_ declFixity (\(fixity, alias) -> fixityAsMarkdown fixity alias >> spacer)

for_ declComments tell'

Expand All @@ -68,9 +68,11 @@ codeToString = outputWith elemAsMarkdown
elemAsMarkdown (Keyword x) = x
elemAsMarkdown Space = " "

fixityAsMarkdown :: P.Fixity -> Docs
fixityAsMarkdown (P.Fixity associativity precedence) =
fixityAsMarkdown :: P.Fixity -> Maybe String -> Docs
fixityAsMarkdown (P.Fixity associativity precedence) alias =
-- TODO: link alias name to member
tell' $ concat [ "_"
, maybe "" (\i -> "alias for " ++ i ++ " - ") alias
, associativityStr
, " / precedence "
, show precedence
Expand Down
17 changes: 10 additions & 7 deletions src/Language/PureScript/Docs/Convert.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ module Language.PureScript.Docs.Convert
, collectBookmarks
) where

import Prelude ()
import Prelude.Compat

import Control.Monad
import Control.Category ((>>>))
import Data.Either
Expand Down Expand Up @@ -68,7 +71,7 @@ type IntermediateDeclaration
-- with their associativity and precedence.
data DeclarationAugment
= AugmentChild ChildDeclaration
| AugmentFixity P.Fixity
| AugmentFixity P.Fixity (Maybe P.Ident)

-- | Augment top-level declarations; the second pass. See the comments under
-- the type synonym IntermediateDeclaration for more information.
Expand All @@ -86,8 +89,8 @@ augmentDeclarations (partitionEithers -> (augments, toplevels)) =
case a of
AugmentChild child ->
d { declChildren = declChildren d ++ [child] }
AugmentFixity fixity ->
d { declFixity = Just fixity }
AugmentFixity fixity alias ->
d { declFixity = Just (fixity, P.runIdent <$> alias) }

-- | Add the default operator fixity for operators which do not have associated
-- fixity declarations.
Expand All @@ -97,7 +100,7 @@ augmentDeclarations (partitionEithers -> (augments, toplevels)) =
addDefaultFixity :: Declaration -> Declaration
addDefaultFixity decl@Declaration{..}
| isOp declTitle && isNothing declFixity =
decl { declFixity = Just defaultFixity }
decl { declFixity = Just (defaultFixity, Nothing) }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checking: once we require operators to be defined as aliases for other existing values, this addDefaultFixity function will no longer be necessary, right?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's right.

| otherwise =
decl
where
Expand All @@ -113,7 +116,7 @@ getDeclarationTitle (P.ExternDataDeclaration name _) = Just (P.runProper
getDeclarationTitle (P.TypeSynonymDeclaration name _ _) = Just (P.runProperName name)
getDeclarationTitle (P.TypeClassDeclaration name _ _ _) = Just (P.runProperName name)
getDeclarationTitle (P.TypeInstanceDeclaration name _ _ _ _) = Just (P.showIdent name)
getDeclarationTitle (P.FixityDeclaration _ name) = Just ("(" ++ name ++ ")")
getDeclarationTitle (P.FixityDeclaration _ name _) = Just ("(" ++ name ++ ")")
getDeclarationTitle (P.PositionedDeclaration _ _ d) = getDeclarationTitle d
getDeclarationTitle _ = Nothing

Expand Down Expand Up @@ -170,8 +173,8 @@ convertDeclaration (P.TypeInstanceDeclaration _ constraints className tys _) tit

childDecl = ChildDeclaration title Nothing Nothing (ChildInstance constraints classApp)
classApp = foldl P.TypeApp (P.TypeConstructor className) tys
convertDeclaration (P.FixityDeclaration fixity _) title =
Just (Left ([title], AugmentFixity fixity))
convertDeclaration (P.FixityDeclaration fixity _ alias) title =
Just (Left ([title], AugmentFixity fixity alias))
convertDeclaration (P.PositionedDeclaration srcSpan com d') title =
fmap (addComments . addSourceSpan) (convertDeclaration d' title)
where
Expand Down
11 changes: 7 additions & 4 deletions src/Language/PureScript/Docs/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ data Declaration = Declaration
, declComments :: Maybe String
, declSourceSpan :: Maybe P.SourceSpan
, declChildren :: [ChildDeclaration]
, declFixity :: Maybe P.Fixity
, declFixity :: Maybe (P.Fixity, Maybe String)
, declInfo :: DeclarationInfo
}
deriving (Show, Eq, Ord)
Expand Down Expand Up @@ -307,9 +307,12 @@ asDeclaration =
<*> key "fixity" (perhaps asFixity)
<*> key "info" asDeclarationInfo

asFixity :: Parse PackageError P.Fixity
asFixity = P.Fixity <$> key "associativity" asAssociativity
<*> key "precedence" asIntegral
asFixity :: Parse PackageError (P.Fixity, Maybe String)
asFixity = do
fixity <- P.Fixity <$> key "associativity" asAssociativity
<*> key "precedence" asIntegral
alias <- keyMay "alias" asString
return (fixity, alias)

parseAssociativity :: String -> Maybe P.Associativity
parseAssociativity str = case str of
Expand Down
14 changes: 12 additions & 2 deletions src/Language/PureScript/Errors.hs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ data SimpleErrorMessage
| UnusedExplicitImport ModuleName [String]
| UnusedDctorImport ProperName
| UnusedDctorExplicitImport ProperName [ProperName]
| DeprecatedOperatorDecl String
| DeprecatedQualifiedSyntax ModuleName ModuleName
| DeprecatedClassImport ModuleName ProperName
| DeprecatedClassExport ProperName
Expand Down Expand Up @@ -271,6 +272,7 @@ errorCode em = case unwrapErrorMessage em of
UnusedExplicitImport{} -> "UnusedExplicitImport"
UnusedDctorImport{} -> "UnusedDctorImport"
UnusedDctorExplicitImport{} -> "UnusedDctorExplicitImport"
DeprecatedOperatorDecl{} -> "DeprecatedOperatorDecl"
DeprecatedQualifiedSyntax{} -> "DeprecatedQualifiedSyntax"
DeprecatedClassImport{} -> "DeprecatedClassImport"
DeprecatedClassExport{} -> "DeprecatedClassExport"
Expand Down Expand Up @@ -712,8 +714,9 @@ prettyPrintSingleError full level e = do
, line "All types appearing in instance declarations must be of the form T a_1 .. a_n, where each type a_i is of the same form."
]
renderSimpleErrorMessage (TransitiveExportError x ys) =
paras $ line ("An export for " ++ prettyPrintExport x ++ " requires the following to also be exported: ")
: map (line . prettyPrintExport) ys
paras [ line $ "An export for " ++ prettyPrintExport x ++ " requires the following to also be exported: "
, indent $ paras $ map (line . prettyPrintExport) ys
]
renderSimpleErrorMessage (ShadowedName nm) =
line $ "Name '" ++ showIdent nm ++ "' was shadowed."
renderSimpleErrorMessage (ShadowedTypeVar tv) =
Expand Down Expand Up @@ -770,6 +773,13 @@ prettyPrintSingleError full level e = do
paras [ line $ "The import of type " ++ runProperName name ++ " includes the following unused data constructors:"
, indent $ paras $ map (line .runProperName) names ]

renderSimpleErrorMessage (DeprecatedOperatorDecl name) =
paras [ line $ "The operator (" ++ name ++ ") was declared as a value rather than an alias for a named function."
, line "Operator aliases are declared by using a fixity declaration, for example:"
, indent $ line $ "infixl 9 someFunction as " ++ name
, line $ "Support for value-declared operators will be removed in PureScript 0.9."
]

renderSimpleErrorMessage (DeprecatedQualifiedSyntax name qualName) =
paras [ line $ "Import uses the deprecated 'qualified' syntax:"
, indent $ line $ "import qualified " ++ runModuleName name ++ " as " ++ runModuleName qualName
Expand Down
22 changes: 6 additions & 16 deletions src/Language/PureScript/Externs.hs
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
-----------------------------------------------------------------------------
--
-- Module : Language.PureScript.Externs
-- Copyright : (c) 2013-15 Phil Freeman, (c) 2014-15 Gary Burgess
-- License : MIT (http://opensource.org/licenses/MIT)
--
-- Maintainer : Phil Freeman <paf31@cantab.net>
-- Stability : experimental
-- Portability :
--
-- |
-- This module generates code for \"externs\" files, i.e. files containing only foreign import declarations.
--
-----------------------------------------------------------------------------

{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE PatternGuards #-}
{-# LANGUAGE TemplateHaskell #-}

-- |
-- This module generates code for \"externs\" files, i.e. files containing only foreign import declarations.
--
module Language.PureScript.Externs
( ExternsFile(..)
, ExternsImport(..)
Expand Down Expand Up @@ -84,6 +72,8 @@ data ExternsFixity = ExternsFixity
, efPrecedence :: Precedence
-- | The operator symbol
, efOperator :: String
-- | The value the operator is an alias for
, efAlias :: Maybe Ident
} deriving (Show, Read)

-- | A type or value declaration appearing in an externs file
Expand Down Expand Up @@ -163,7 +153,7 @@ moduleToExternsFile (Module _ _ mn ds (Just exps)) env = ExternsFile{..}
efDeclarations = concatMap toExternsDeclaration efExports

fixityDecl :: Declaration -> Maybe ExternsFixity
fixityDecl (FixityDeclaration (Fixity assoc prec) op) = fmap (const (ExternsFixity assoc prec op)) (find exportsOp exps)
fixityDecl (FixityDeclaration (Fixity assoc prec) op alias) = fmap (const (ExternsFixity assoc prec op alias)) (find exportsOp exps)
where
exportsOp :: DeclarationRef -> Bool
exportsOp (PositionedDeclarationRef _ _ r) = exportsOp r
Expand Down
22 changes: 6 additions & 16 deletions src/Language/PureScript/Linter.hs
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
-----------------------------------------------------------------------------
--
-- Module : Language.PureScript.Linter
-- Copyright : (c) 2013-15 Phil Freeman, (c) 2014-15 Gary Burgess
-- License : MIT (http://opensource.org/licenses/MIT)
--
-- Maintainer : Phil Freeman <paf31@cantab.net>
-- Stability : experimental
-- Portability :
--
-- | This module implements a simple linting pass on the PureScript AST.
--
-----------------------------------------------------------------------------

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PatternGuards #-}

-- |
-- This module implements a simple linting pass on the PureScript AST.
--
module Language.PureScript.Linter (lint, module L) where

import Prelude ()
Expand Down Expand Up @@ -66,11 +55,12 @@ lint (Module _ _ mn ds _) = censor (addHint (ErrorInModule mn)) $ mapM_ lintDecl
f dec = warningsInDecl moduleNames dec <> checkTypeVarsInDecl dec

stepD :: S.Set Ident -> Declaration -> MultipleErrors
stepD _ (TypeClassDeclaration name _ _ decls) = foldMap go decls
stepD _ (ValueDeclaration (Op name) _ _ _) = errorMessage (DeprecatedOperatorDecl name)
stepD _ (TypeClassDeclaration _ _ _ decls) = foldMap go decls
where
go :: Declaration -> MultipleErrors
go (PositionedDeclaration _ _ d') = go d'
go (TypeDeclaration op@(Op _) _) = errorMessage (ClassOperator name op)
go (TypeDeclaration (Op name) _) = errorMessage (DeprecatedOperatorDecl name)
go _ = mempty
stepD _ _ = mempty

Expand Down
3 changes: 2 additions & 1 deletion src/Language/PureScript/Parser/Declarations.hs
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,9 @@ parseFixityDeclaration :: TokenParser Declaration
parseFixityDeclaration = do
fixity <- parseFixity
indented
alias <- P.optionMaybe $ (Ident <$> identifier) <* reserved "as"
name <- symbol
return $ FixityDeclaration fixity name
return $ FixityDeclaration fixity name alias

parseImportDeclaration :: TokenParser Declaration
parseImportDeclaration = do
Expand Down
1 change: 1 addition & 0 deletions src/Language/PureScript/Sugar/Names/Exports.hs
Loading