CoreFn is the core functional intermediate representation used in the PureScript compiler. It serves as the bridge between the high-level Abstract Syntax Tree (AST) and the imperative CoreImp representation, providing a simplified functional language that eliminates syntactic sugar while preserving semantic information.
The fundamental expression types in the CoreFn representation, covering all functional constructs after desugaring.
-- | Core functional expressions
data Expr a
= Literal a (Literal (Expr a)) -- Literal values
| Constructor a (ProperName 'TypeName) (ProperName 'ConstructorName) [Ident] -- Data constructors
| Accessor a PSString (Expr a) -- Record property access
| ObjectUpdate a (Expr a) (Maybe [PSString]) [(PSString, Expr a)] -- Record updates
| Abs a Ident (Expr a) -- Lambda abstractions
| App a (Expr a) (Expr a) -- Function application
| Var a (Qualified Ident) -- Variables
| Case a [Expr a] [CaseAlternative a] -- Pattern matching
| Let a [Bind a] (Expr a) -- Let bindings
-- | Case alternatives with pattern matching
data CaseAlternative a = CaseAlternative
{ caseAlternativeBinders :: [Binder a] -- Pattern binders
, caseAlternativeResult :: Either [(Guard a, Expr a)] (Expr a) -- Guarded or simple result
}
-- | Guards for conditional expressions
type Guard a = Expr aBinding forms for let expressions and module-level definitions.
-- | Let and module bindings
data Bind a
= NonRec a Ident (Expr a) -- Non-recursive binding
| Rec [((a, Ident), Expr a)] -- Recursive binding groupComplete module structure in CoreFn form with imports, exports, and declarations.
-- | CoreFn module representation
data Module a = Module
{ moduleSourceSpan :: SourceSpan -- Source location
, moduleComments :: [Comment] -- Module comments
, moduleName :: ModuleName -- Module name
, modulePath :: FilePath -- Source file path
, moduleImports :: [(a, ModuleName)] -- Import list with annotations
, moduleExports :: [Ident] -- Exported identifiers
, moduleReExports :: Map ModuleName [Ident] -- Re-exported identifiers
, moduleForeign :: [Ident] -- Foreign function imports
, moduleDecls :: [Bind a] -- Module declarations
}Functions for converting high-level AST to CoreFn representation, performing desugaring and simplification.
-- | Convert a module from AST to CoreFn
moduleToCoreFn :: Module -> m (Module CoreFn.Ann)
-- | Convert expressions from AST to CoreFn
exprToCoreFn :: Expr -> m (CoreFn.Expr CoreFn.Ann)
-- | Convert declarations to CoreFn bindings
declToCoreFn :: Declaration -> m [CoreFn.Bind CoreFn.Ann]Optimization passes that operate on the CoreFn representation to improve performance and eliminate dead code.
-- | Optimize a CoreFn module
optimizeCoreFn :: Module CoreFn.Ann -> Module CoreFn.Ann
-- | Inline simple bindings and constants
inlineCoreFn :: Module CoreFn.Ann -> Module CoreFn.Ann
-- | Remove unused bindings and expressions
eliminateDeadCodeCoreFn :: Module CoreFn.Ann -> Module CoreFn.AnnSerialization functions for persisting and loading CoreFn modules in JSON format.
-- | Convert CoreFn module to JSON
moduleToJSON :: Module CoreFn.Ann -> Value
-- | Parse CoreFn module from JSON
moduleFromJSON :: Value -> Either String (Module CoreFn.Ann)
-- | Convert CoreFn expression to JSON
exprToJSON :: Expr CoreFn.Ann -> Value
-- | Parse CoreFn expression from JSON
exprFromJSON :: Value -> Either String (Expr CoreFn.Ann)Generic traversal and analysis functions for working with CoreFn structures.
-- | Transform all expressions in a module
everywhereOnValues :: (Bind a -> Bind a) -> (Expr a -> Expr a) -> (Binder a -> Binder a) -> Module a -> Module a
-- | Collect information from all expressions in a module
everythingOnValues :: Monoid r => (Bind a -> r) -> (Expr a -> r) -> (Binder a -> r) -> Module a -> r
-- | Transform expressions with context
transformCoreFn :: (Expr a -> Expr a) -> Module a -> Module aAnnotation types used throughout CoreFn to preserve source information and metadata.
-- | CoreFn annotations with source positions and metadata
data Ann = Ann
{ annSourceSpan :: SourceSpan -- Source location
, annComments :: [Comment] -- Associated comments
, annType :: Maybe Type -- Type information
, annMeta :: Maybe Meta -- Compiler metadata
}
-- | Metadata for CoreFn expressions
data Meta
= IsConstructor -- Constructor application
| IsNewtype -- Newtype constructor
| IsTypeClassConstructor -- Type class dictionary
| IsForeign -- Foreign function
| IsWhere -- Where clause binding
| ConstructorType [Ident] [Ident] -- Constructor field infoimport Language.PureScript.CoreFn
-- Create a simple lambda expression: \x -> x
identityExpr :: Expr Ann
identityExpr = Abs ann (Ident "x") (Var ann (Qualified Nothing (Ident "x")))
where ann = Ann defaultSourceSpan [] Nothing Nothing
-- Create a function application: f x
appExpr :: Expr Ann -> Expr Ann -> Expr Ann
appExpr f x = App ann f x
where ann = Ann defaultSourceSpan [] Nothing Nothing-- Extract all variable references from a module
extractVars :: Module Ann -> [Qualified Ident]
extractVars = everythingOnValues (const mempty) getVars (const mempty)
where
getVars (Var _ name) = [name]
getVars _ = []
-- Transform all lambdas in a module
transformLambdas :: (Ident -> Expr Ann -> Expr Ann) -> Module Ann -> Module Ann
transformLambdas f = everywhereOnValues id transformExpr id
where
transformExpr (Abs ann ident body) = f ident (Abs ann ident body)
transformExpr expr = expr-- Save a CoreFn module to a file
saveCoreFnModule :: FilePath -> Module Ann -> IO ()
saveCoreFnModule path modul = do
let json = moduleToJSON modul
encodeFile path json
-- Load a CoreFn module from a file
loadCoreFnModule :: FilePath -> IO (Either String (Module Ann))
loadCoreFnModule path = do
result <- eitherDecodeFileStrict path
return $ result >>= moduleFromJSON