egison-5.0.0: hs-src/Language/Egison/Type/TypedDesugar.hs
{- |
Module : Language.Egison.Type.TypedDesugar
Licence : MIT
This module implements Phase 8 of the processing flow: TypedDesugar.
It orchestrates type-driven transformations on TIExpr (Typed Internal Expressions)
by calling specialized expansion modules.
Type-Driven Transformations (Phase 8):
1. Type class dictionary passing (via TypeClassExpand)
- Instance selection based on types
- Method call concretization
2. Type information optimization and embedding
- Preserve type info for better error messages during evaluation
- Each node in TIExpr contains its type
Type information is preserved throughout desugaring, enabling:
- Better runtime error messages with type information
- Type-based dispatch during evaluation
- Debugging support with type annotations
-}
module Language.Egison.Type.TypedDesugar
( desugarTypedExprT
, desugarTypedTopExprT
, desugarTypedTopExprT_TensorMapOnly
, desugarTypedTopExprT_TypeClassOnly
) where
import Language.Egison.Data (EvalM)
import Language.Egison.EvalState (MonadEval(..))
import Language.Egison.IExpr (TIExpr(..), TITopExpr(..), extractNameFromVar, stringToVar)
import Language.Egison.Type.Env (lookupEnv)
import Language.Egison.Type.TensorMapInsertion (insertTensorMaps)
import Language.Egison.Type.TypeClassExpand (expandTypeClassMethodsT, expandTypeClassMethodsInPattern, addDictionaryParametersT, applyConcreteConstraintDictionaries, applyConcreteConstraintDictionariesInPattern)
-- | Desugar a typed expression (TIExpr) with type-driven transformations
-- This function orchestrates the transformation pipeline:
-- 1. Insert tensorMap where needed (TensorMapInsertion)
-- 2. Expand type class methods (dictionary passing)
--
-- The order matters: tensorMap insertion should happen before type class expansion
-- because after tensorMap insertion, argument types (scalar vs tensor) are determined,
-- which allows type class expansion to use unifyStrict for instance selection.
desugarTypedExprT :: TIExpr -> EvalM TIExpr
desugarTypedExprT tiexpr = do
-- Step 1: Insert tensorMap where needed
tiexpr' <- insertTensorMaps tiexpr
-- Step 2: Expand type class methods (dictionary passing)
tiexpr'' <- expandTypeClassMethodsT tiexpr'
return tiexpr''
-- | Desugar a top-level typed expression (TITopExpr)
-- This is the main entry point for Phase 8 transformations.
desugarTypedTopExprT :: TITopExpr -> EvalM (Maybe TITopExpr)
desugarTypedTopExprT topExpr = case topExpr of
TIDefine scheme var tiexpr -> do
tiexpr' <- desugarTypedExprT tiexpr
-- Apply dictionaries to right-hand side if it has concrete type constraints
tiexpr'' <- applyConcreteConstraintDictionaries tiexpr'
-- Add dictionary parameters for constrained functions
tiexpr''' <- addDictionaryParametersT scheme tiexpr''
return $ Just (TIDefine scheme var tiexpr''')
TITest tiexpr -> do
tiexpr' <- desugarTypedExprT tiexpr
return $ Just (TITest tiexpr')
TIExecute tiexpr -> do
tiexpr' <- desugarTypedExprT tiexpr
return $ Just (TIExecute tiexpr')
TILoadFile path ->
return $ Just (TILoadFile path)
TILoad lib ->
return $ Just (TILoad lib)
TIDefineMany bindings -> do
bindings' <- mapM (\(var, tiexpr) -> do
tiexpr' <- desugarTypedExprT tiexpr
-- Add dictionary parameters using the variable's type scheme from TypeEnv
-- This is important for dictionary definitions where the expression (hash)
-- may not have constraints, but the variable has constraints in its type scheme
typeEnv <- getTypeEnv
let varName = extractNameFromVar var
scheme = case lookupEnv (stringToVar varName) typeEnv of
Just ts -> ts -- Use type scheme from environment
Nothing -> tiScheme tiexpr' -- Fallback to expression's scheme
tiexpr'' <- addDictionaryParametersT scheme tiexpr'
return (var, tiexpr'')) bindings
return $ Just (TIDefineMany bindings')
TIDeclareSymbol names ty ->
-- Symbol declarations don't need type-driven transformations
return $ Just (TIDeclareSymbol names ty)
TIPatternFunctionDecl name typeScheme params retType body -> do
-- Pattern function declarations: apply type class expansion and dictionary application to body
body' <- expandTypeClassMethodsInPattern body
body'' <- applyConcreteConstraintDictionariesInPattern body'
return $ Just (TIPatternFunctionDecl name typeScheme params retType body'')
-- | Desugar a top-level typed expression with TensorMap insertion only
-- This is used for --dump-ti (intermediate dump after TensorMap insertion)
desugarTypedTopExprT_TensorMapOnly :: TITopExpr -> EvalM (Maybe TITopExpr)
desugarTypedTopExprT_TensorMapOnly topExpr = case topExpr of
TIDefine scheme var tiexpr -> do
-- Only insert tensorMap (no type class expansion)
tiexpr' <- insertTensorMaps tiexpr
return $ Just (TIDefine scheme var tiexpr')
TITest tiexpr -> do
tiexpr' <- insertTensorMaps tiexpr
return $ Just (TITest tiexpr')
TIExecute tiexpr -> do
tiexpr' <- insertTensorMaps tiexpr
return $ Just (TIExecute tiexpr')
TILoadFile path ->
return $ Just (TILoadFile path)
TILoad lib ->
return $ Just (TILoad lib)
TIDefineMany bindings -> do
bindings' <- mapM (\(var, tiexpr) -> do
tiexpr' <- insertTensorMaps tiexpr
return (var, tiexpr')) bindings
return $ Just (TIDefineMany bindings')
TIDeclareSymbol names ty ->
return $ Just (TIDeclareSymbol names ty)
TIPatternFunctionDecl name typeScheme params retType body ->
-- Pattern function declarations: TensorMap insertion only
return $ Just (TIPatternFunctionDecl name typeScheme params retType body)
-- | Expand type class methods only (assumes TensorMap insertion is already done)
-- This is used internally to perform type class expansion after TensorMap insertion
desugarTypedTopExprT_TypeClassOnly :: TITopExpr -> EvalM (Maybe TITopExpr)
desugarTypedTopExprT_TypeClassOnly topExpr = case topExpr of
TIDefine scheme var tiexpr -> do
-- Only expand type class methods (assumes tensorMap is already inserted)
tiexpr' <- expandTypeClassMethodsT tiexpr
-- Apply dictionaries to right-hand side if it has concrete type constraints
tiexpr'' <- applyConcreteConstraintDictionaries tiexpr'
-- Add dictionary parameters for constrained functions
tiexpr''' <- addDictionaryParametersT scheme tiexpr''
return $ Just (TIDefine scheme var tiexpr''')
TITest tiexpr -> do
tiexpr' <- expandTypeClassMethodsT tiexpr
return $ Just (TITest tiexpr')
TIExecute tiexpr -> do
tiexpr' <- expandTypeClassMethodsT tiexpr
return $ Just (TIExecute tiexpr')
TILoadFile path ->
return $ Just (TILoadFile path)
TILoad lib ->
return $ Just (TILoad lib)
TIDefineMany bindings -> do
bindings' <- mapM (\(var, tiexpr) -> do
tiexpr' <- expandTypeClassMethodsT tiexpr
-- Add dictionary parameters using the variable's type scheme from TypeEnv
typeEnv <- getTypeEnv
let varName = extractNameFromVar var
scheme = case lookupEnv (stringToVar varName) typeEnv of
Just ts -> ts
Nothing -> tiScheme tiexpr'
tiexpr'' <- addDictionaryParametersT scheme tiexpr'
return (var, tiexpr'')) bindings
return $ Just (TIDefineMany bindings')
TIDeclareSymbol names ty ->
return $ Just (TIDeclareSymbol names ty)
TIPatternFunctionDecl name typeScheme params retType body -> do
-- Pattern function declarations: expand type class methods and apply dictionaries in body
body' <- expandTypeClassMethodsInPattern body
body'' <- applyConcreteConstraintDictionariesInPattern body'
return $ Just (TIPatternFunctionDecl name typeScheme params retType body'')