File size: 4,740 Bytes
a10b189 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
{-|
Module : Assertica.Backend.TypeCompiler
Description : Compile Assertica types to Haskell type signatures
Copyright : (c) 2026 Ahmad Ali Parr
License : BSL-1.0
Translates type expressions from the Core AST to Haskell type syntax:
MAPPINGS:
- TyVar v β v (type variable)
- TyConst C [T1, ..., Tn] β C T1 ... Tn (type constructor application)
- TyFun A B β A -> B (function type)
- TyForall (x : A) . B β forall x . A -> B (dependent function)
- TyUniverse Type0 β Type (type universe)
- TyUniverse (TypeN n) β Type (all universes collapse to Type in Haskell)
- TyApp T1 T2 β T1 T2 (type application)
- TyEq a b β (a :~: b) (equality type using GADT)
UNIVERSE MAPPING:
Assertica's universe hierarchy (Type 0, Type 1, ...) is mapped to Haskell's
single-level kind system. All universes compile to "Type" or higher kinds
as appropriate for the context.
DEPENDENT TYPES:
Assertica supports full dependent types via TyForall. These are mapped to
Haskell functions or GADT syntax where possible. Complex dependent types
may require GADT encoding with indices.
PRINCIPLES:
1. **Type Safety**: Generated types are valid Haskell 2010 / GHC extensions
2. **Determinism**: Same type input produces same output
3. **Readability**: Generated types are human-readable
4. **No Generics**: Avoid needing exotic extensions where possible
-}
module Assertica.Backend.TypeCompiler
( -- * Main compilation function
compileType
, compileTypeWith
) where
import Data.Text (Text)
import qualified Data.Text as T
import Data.List (intercalate)
import qualified Data.Set as Set
import GHC.Generics (Generic)
import Assertica.Core.AST
import Assertica.Backend.CodeGen (CodeGenConfig)
import qualified Assertica.Backend.TermCompiler as TC
-- ============================================================================
-- MAIN COMPILATION FUNCTION
-- ============================================================================
{-| Compile a type to Haskell type syntax.
This is the primary entry point for type compilation.
Returns either a Haskell type expression string or an error.
-}
compileType :: CodeGenConfig -> Type -> Either String Text
compileType config ty = compileTypeWith config Set.empty ty
{-| Compile a type with a given bound variable context -}
compileTypeWith :: CodeGenConfig -> Set.Set Var -> Type -> Either String Text
compileTypeWith config bound = \case
TyVar (Var name _) -> Right name
TyConst (QName mod name) args -> do
compiledArgs <- mapM (compileTypeWith config bound) args
let qname = if null mod
then name
else T.intercalate "." mod <> "." <> name
if null compiledArgs
then Right qname
else Right $ "(" <> qname <> " " <> T.intercalate " " compiledArgs <> ")"
TyFun a b -> do
ca <- compileTypeWith config bound a
cb <- compileTypeWith config bound b
Right $ "(" <> ca <> " -> " <> cb <> ")"
TyForall (Binder (Var name _) _) body ->
-- Dependent function type: forall x . body
-- In Haskell, this becomes a higher-order function type
let bound' = Set.insert (Var name 0) bound
in do
cb <- compileTypeWith config bound' body
Right $ "(forall (" <> name <> ") . " <> cb <> ")"
TyUniverse Type0 ->
-- Type 0 β Haskell's Type kind
Right "Type"
TyUniverse (TypeN _n) ->
-- Higher universes also map to Type in Haskell
-- (Haskell doesn't have predicative universes)
Right "Type"
TyApp t1 t2 -> do
ct1 <- compileTypeWith config bound t1
ct2 <- compileTypeWith config bound t2
-- Type application: just juxtapose
Right $ "(" <> ct1 <> " " <> ct2 <> ")"
TyEq e1 e2 -> do
-- Equality type: compile using GADT syntax
-- TyEq a b becomes (a :~: b) using GADT machinery
_ce1 <- TC.compileTerm config e1
_ce2 <- TC.compileTerm config e2
-- For now, return a placeholder
-- In a full implementation, would use GADT.Equality machinery
Right "Equality"
-- ============================================================================
-- UNIVERSE HANDLING
-- ============================================================================
{-| Map Assertica universe levels to Haskell kinds -}
universeToKind :: TypeLevel -> Text
universeToKind = \case
Type0 -> "Type"
TypeN _ -> "Type" -- All universes collapse to Type
{-| Check if a type is well-formed at a given universe level -}
-- This would be more complex in a production system
isWellFormedAtLevel :: TypeLevel -> Type -> Bool
isWellFormedAtLevel _level _ty =
True -- Simplified for now
|