The Sugar modules implement the desugaring pipeline that transforms high-level PureScript syntax into simpler, more explicit forms. This pipeline runs after parsing but before type checking, eliminating syntactic conveniences and expanding them into their underlying representations.
The complete desugaring transformation that processes modules through all desugaring passes in the correct order.
-- | Main desugaring function that applies all passes
desugar :: [ExternsFile] -> Module -> StateT (Env, UsedImports) (SupplyT (Either MultipleErrors)) Module
-- | The complete desugaring pipeline includes:
-- 1. Remove signed literals (replace with negate applications)
-- 2. Desugar object wildcards into lambdas
-- 3. Desugar operator sections
-- 4. Desugar do-notation into bind applications
-- 5. Desugar ado-notation into apply applications
-- 6. Desugar case declarations into case expressions
-- 7. Desugar type declarations into type annotations
-- 8. Qualify unqualified names and types
-- 9. Rebracket user-defined operators
-- 10. Introduce type class dictionaries and instances
-- 11. Create binding groups for mutually recursive definitionsTransforms do-notation blocks into explicit bind and discard applications using the Monad type class.
-- | Desugar do-notation in a module
desugarDoModule :: Module -> m Module
-- | Do notation elements before desugaring
data DoNotationElement
= DoNotationValue Expr -- Pure expression
| DoNotationBind Binder Expr -- Monadic bind
| DoNotationLet [Declaration] -- Let binding
| PositionedDoNotationElement SourcePos [Comment] DoNotationElement
-- | Transform do-notation to bind applications
-- do { x <- m; f x } becomes m >>= \x -> f x
-- do { m; n } becomes m >> n
-- do { let x = y; m } becomes let x = y in m
desugarDoStatement :: DoNotationElement -> Expr -> m ExprTransforms ado-notation blocks into explicit apply applications using the Apply type class for applicative computations.
-- | Desugar ado-notation in a module
desugarAdoModule :: Module -> m Module
-- | Transform ado-notation to apply applications
-- ado { x <- m1; y <- m2; in f x y } becomes lift2 f m1 m2
-- ado { x <- m1; let y = g x; in f x y } becomes m1 <#> \x -> let y = g x in f x y
desugarAdoStatement :: [DoNotationElement] -> Expr -> m ExprHandles operator precedence, associativity, and sections (partial application of operators).
-- | Rebracket operators according to precedence and associativity
rebracketOperators :: Module -> m Module
-- | Desugar operator sections into lambda expressions
desugarOperatorSections :: Module -> m Module
-- | Operator fixity information
data Fixity = Fixity Associativity Precedence
data Associativity = Infixl | Infixr | Infix
type Precedence = Integer
-- | Transform operator sections:
-- (+ 1) becomes \x -> x + 1
-- (1 +) becomes \x -> 1 + x
-- (+) becomes \x y -> x + y
desugarOperatorSection :: Expr -> m ExprTransforms type class instances into dictionary types and replaces constrained types with dictionary parameters.
-- | Desugar type classes and instances
desugarTypeClasses :: [ExternsFile] -> Module -> m Module
-- | Transform type class into newtype dictionary
-- class Show a where show :: a -> String
-- becomes: newtype Show a = Show { show :: a -> String }
desugarTypeClass :: Declaration -> m [Declaration]
-- | Transform instance into dictionary value
-- instance showInt :: Show Int where show = showIntImpl
-- becomes: showInt :: Show Int; showInt = Show { show: showIntImpl }
desugarInstance :: Declaration -> m [Declaration]
-- | Replace constrained types with dictionary parameters
-- f :: Show a => a -> String becomes f :: Show a -> a -> String
desugarConstrainedType :: Type -> m TypeAutomatically generates type class instances for data types using deriving clauses.
-- | Generate derived instances for data types
deriveInstances :: Module -> m Module
-- | Derivable type classes
data DeriveClass
= Eq -- Structural equality
| Ord -- Structural ordering
| Functor -- Functor mapping
| Generic -- Generic representation
| Newtype -- Newtype wrapping/unwrapping
-- | Generate instance for a derivable class
deriveInstance :: DeriveClass -> DataDeclaration -> m DeclarationTransforms object patterns with wildcards into explicit lambda expressions.
-- | Desugar object wildcards
desugarObjectWildcards :: Module -> m Module
-- | Transform record wildcards:
-- { x, y, .. } becomes \r -> { x: r.x, y: r.y, z: r.z, ... }
-- where .. represents all other fields in scope
desugarObjectWildcard :: Expr -> m ExprConverts top-level pattern matching function definitions into explicit case expressions.
-- | Desugar case declarations
desugarCaseDeclarations :: Module -> m Module
-- | Transform pattern matching function definitions:
-- f true = 1
-- f false = 2
-- becomes: f = \x -> case x of { true -> 1; false -> 2 }
desugarCaseDeclaration :: [Declaration] -> m DeclarationResolves unqualified names by looking them up in the current scope and qualifying them appropriately.
-- | Qualify all names in a module
qualifyNames :: Module -> m Module
-- | Resolve and qualify a name
qualifyName :: Ident -> m (Qualified Ident)
-- | Resolve and qualify a type name
qualifyTypeName :: ProperName 'TypeName -> m (Qualified (ProperName 'TypeName))
-- | Name resolution environment
data Env = Env
{ envModuleName :: ModuleName -- Current module
, envImports :: ImportedModules -- Available imports
, envTypeClassDictionaries :: Map (Qualified Ident) TypeClassDictionaryInScope
, envNameKinds :: Map (Qualified Ident) (Type (), NameKind)
}Analyzes dependencies between declarations and creates mutually recursive binding groups.
-- | Create binding groups for mutually recursive definitions
createBindingGroups :: Module -> m Module
-- | A binding group of mutually recursive declarations
data BindingGroup = BindingGroup
{ bindingGroupDeclarations :: [Declaration] -- Group members
, bindingGroupDependencies :: [Ident] -- External dependencies
}
-- | Analyze dependencies between declarations
analyzeDependencies :: [Declaration] -> DependencyGraph
-- | Strongly connected components for mutual recursion
createSCCs :: DependencyGraph -> [BindingGroup]Transforms pattern matches in let bindings into case expressions.
-- | Desugar let patterns
desugarLetPatterns :: Module -> m Module
-- | Transform let pattern bindings:
-- let { x, y } = record in expr
-- becomes: case record of { x, y } -> expr
desugarLetPattern :: Declaration -> m DeclarationConverts separate type signatures into inline type annotations on value declarations.
-- | Desugar type declarations
desugarTypeDeclarations :: Module -> m Module
-- | Attach type annotations to value declarations
-- f :: Int -> Int; f x = x + 1
-- becomes: f :: Int -> Int; f = (\x -> x + 1) :: Int -> Int
attachTypeAnnotation :: Declaration -> Declaration -> m Declarationimport Language.PureScript.Sugar
-- Desugar a complete module
desugarModule :: [ExternsFile] -> Module -> Either MultipleErrors Module
desugarModule externs modul =
evalSupply 0 $ runExceptT $ evalStateT (desugar externs modul) (emptyEnv, mempty)
-- Desugar just do-notation
desugarDoOnly :: Module -> Either MultipleErrors Module
desugarDoOnly modul =
evalSupply 0 $ runExceptT $ desugarDoModule modul-- Input do-notation:
-- do
-- x <- action1
-- y <- action2 x
-- pure (x + y)
-- Output after desugaring:
-- action1 >>= \x ->
-- action2 x >>= \y ->
-- pure (x + y)-- Input ado-notation:
-- ado
-- x <- action1
-- y <- action2
-- in f x y
-- Output after desugaring:
-- lift2 f action1 action2-- Input type class:
-- class Show a where
-- show :: a -> String
-- Output after desugaring:
-- newtype Show a = Show { show :: a -> String }
-- Input instance:
-- instance showInt :: Show Int where
-- show = showIntImpl
-- Output after desugaring:
-- showInt :: Show Int
-- showInt = Show { show: showIntImpl }-- Input operator sections:
map (+ 1) [1, 2, 3] -- Becomes: map (\x -> x + 1) [1, 2, 3]
map (1 +) [1, 2, 3] -- Becomes: map (\x -> 1 + x) [1, 2, 3]
map (+) pairs -- Becomes: map (\x y -> x + y) pairs-- Create a custom desugaring transformation
customDesugar :: Module -> Either MultipleErrors Module
customDesugar modul = do
-- Apply individual passes in order
step1 <- desugarObjectWildcards modul
step2 <- desugarDoModule step1
step3 <- desugarAdoModule step2
step4 <- rebracketOperators step3
desugarTypeClasses [] step4