Download src/Assertica/Backend/TermCompiler.hs from Snapkitty/assertica: direct link, hf CLI and curl.
- Browser
- Download file 7.44 kB
-
https://huggingface.co/Snapkitty/assertica/resolve/main/src/Assertica/Backend/TermCompiler.hs
- Command line
-
hf download hf://Snapkitty/assertica/src/Assertica/Backend/TermCompiler.hs
-
curl -L -o TermCompiler.hs https://huggingface.co/Snapkitty/assertica/resolve/main/src/Assertica/Backend/TermCompiler.hs
7.44 kB
| {-| | |
| Module : Assertica.Backend.TermCompiler | |
| Description : Compile Assertica terms to Haskell expressions | |
| Copyright : (c) 2026 Ahmad Ali Parr | |
| License : BSL-1.0 | |
| Translates computational terms from the Core AST to Haskell expressions: | |
| MAPPINGS: | |
| - Var v β v (variable reference) | |
| - Const c β haskellLiteral c (constant) | |
| - Lam (x : T) . e β \x -> <compiled e> (lambda) | |
| - App f x β (<compiled f>) (<compiled x>) (application) | |
| - Constr C [e1, ..., en] β C e1 ... en (constructor application) | |
| - Case e [p1->b1, ...] def β case e of { p1 -> b1; ... } (case expression) | |
| - Let x = e1 in e2 β let x = <compiled e1> in <compiled e2> | |
| - Ann e T β (<compiled e> :: <compiled T>) (type ascription) | |
| - Forall (x : T) . body β \(x :: <compiled T>) -> <compiled body> (dependent fn) | |
| - ProofTerm p β <compiled p> (proof evidence) | |
| - Prop prop β proof-irrelevant <compiled p> (propositions as terms) | |
| PRINCIPLES: | |
| 1. **Deterministic**: Always produces same output for same input | |
| 2. **Preserve Beta-Equivalence**: Compilation respects computational semantics | |
| 3. **Scope Preservation**: Free/bound variable distinction maintained | |
| 4. **No Code Simplification**: Generate direct translation (optimizer's job) | |
| -} | |
| module Assertica.Backend.TermCompiler | |
| ( -- * Main compilation function | |
| compileTerm | |
| , compilePattern | |
| , compileClause | |
| ) where | |
| import Data.Text (Text) | |
| import qualified Data.Text as T | |
| import Data.List (intercalate, sortBy) | |
| import Data.Ord (comparing) | |
| import qualified Data.Set as Set | |
| import qualified Data.Map.Strict as Map | |
| import GHC.Generics (Generic) | |
| import Assertica.Core.AST | |
| import Assertica.Backend.CodeGen (CodeGenConfig) | |
| -- ============================================================================ | |
| -- MAIN COMPILATION FUNCTION | |
| -- ============================================================================ | |
| {-| Compile a term to Haskell source code. | |
| This is the primary entry point for term compilation. | |
| Returns either a Haskell expression string or an error. | |
| -} | |
| compileTerm :: CodeGenConfig -> Term -> Either String Text | |
| compileTerm config term = compileTermWith config Set.empty term | |
| {-| Compile a term with a given bound variable context. | |
| The bound context tracks variables that are bound by enclosing lambdas, | |
| let-bindings, or other binders, to ensure proper scoping. | |
| -} | |
| compileTermWith :: CodeGenConfig -> Set.Set Var -> Term -> Either String Text | |
| compileTermWith config bound = \case | |
| Var (Var name _) -> | |
| Right $ name | |
| Const c -> Right $ compileConstant c | |
| Lam (Binder (Var name _) _mty) body -> | |
| let bound' = Set.insert (Var name 0) bound -- Simplified: just track name | |
| in do | |
| compiledBody <- compileTermWith config bound' body | |
| Right $ "(\\(" <> name <> ") -> " <> compiledBody <> ")" | |
| App f x -> do | |
| cf <- compileTermWith config bound f | |
| cx <- compileTermWith config bound x | |
| Right $ "(" <> cf <> " " <> cx <> ")" | |
| Constr (QName mod name) args -> do | |
| compiledArgs <- mapM (compileTermWith 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 <> ")" | |
| Case scrutinee clauses defaultClause -> do | |
| cs <- compileTermWith config bound scrutinee | |
| compiledClauses <- mapM (compileClause config bound) clauses | |
| let caseClauses = T.intercalate "; " compiledClauses | |
| let defaultPart = case defaultClause of | |
| Nothing -> "" | |
| Just d -> do | |
| cd <- compileTermWith config bound d | |
| "; _ -> " <> cd | |
| Right $ "(case " <> cs <> " of { " <> caseClauses <> defaultPart <> " })" | |
| Let (Binder (Var name _) _) bindExpr bodyExpr -> do | |
| cb <- compileTermWith config bound bindExpr | |
| let bound' = Set.insert (Var name 0) bound | |
| ce <- compileTermWith config bound' bodyExpr | |
| Right $ "(let " <> name <> " = " <> cb <> " in " <> ce <> ")" | |
| Ann term _ty -> do | |
| -- For now, ignore the type annotation in code gen | |
| -- In a full implementation, could preserve as Haskell type ascription | |
| compileTermWith config bound term | |
| Forall (Binder (Var name _) _) body -> do | |
| -- Dependent function: treat as lambda abstraction | |
| let bound' = Set.insert (Var name 0) bound | |
| cb <- compileTermWith config bound' body | |
| Right $ "(\\(" <> name <> ") -> " <> cb <> ")" | |
| ProofTerm p -> do | |
| -- Proofs compile to evidence terms | |
| compileProofTerm config bound p | |
| Prop prop -> do | |
| -- Propositions as terms become proof-irrelevant () | |
| -- The proposition itself is erased (proof irrelevance) | |
| Right "()" | |
| -- ============================================================================ | |
| -- PATTERN COMPILATION | |
| -- ============================================================================ | |
| {-| Compile a pattern to Haskell pattern syntax -} | |
| compilePattern :: Pattern -> Either String Text | |
| compilePattern = \case | |
| PatVar (Var name _) -> Right name | |
| PatConstr (QName mod name) pats -> do | |
| compiledPats <- mapM compilePattern pats | |
| let qname = if null mod | |
| then name | |
| else T.intercalate "." mod <> "." <> name | |
| if null compiledPats | |
| then Right qname | |
| else Right $ "(" <> qname <> " " <> T.intercalate " " compiledPats <> ")" | |
| PatWildcard -> Right "_" | |
| PatLit lit -> Right $ T.pack lit | |
| {-| Compile a single case clause -} | |
| compileClause :: CodeGenConfig -> Set.Set Var -> Clause -> Either String Text | |
| compileClause config bound (Clause pat body) = do | |
| cp <- compilePattern pat | |
| cb <- compileTermWith config bound body | |
| Right $ cp <> " -> " <> cb | |
| -- ============================================================================ | |
| -- CONSTANT COMPILATION | |
| -- ============================================================================ | |
| {-| Compile a constant value -} | |
| compileConstant :: Constant -> Text | |
| compileConstant = \case | |
| PrimOp op -> compilePrimOp op | |
| IntLit n -> T.pack $ show n | |
| BoolLit b -> T.pack $ show b | |
| StringLit s -> T.pack $ show s | |
| UnitConst -> "()" | |
| ProofConst (QName mod name) -> | |
| if null mod | |
| then name | |
| else T.intercalate "." mod <> "." <> name | |
| {-| Compile a primitive operation to Haskell -} | |
| compilePrimOp :: PrimitiveOp -> Text | |
| compilePrimOp = \case | |
| OpAdd -> "(+)" | |
| OpSub -> "(-)" | |
| OpMul -> "(*)" | |
| OpDiv -> "div" | |
| OpEq -> "(==)" | |
| OpNeq -> "(/=)" | |
| OpLt -> "(<)" | |
| OpLe -> "(<=)" | |
| OpGt -> "(>)" | |
| OpGe -> "(>=)" | |
| OpAnd -> "(&&)" | |
| OpOr -> "(||)" | |
| OpNot -> "not" | |
| OpIfThenElse -> "if" -- Special handling in caller | |
| -- ============================================================================ | |
| -- PROOF TERM COMPILATION (provisional) | |
| -- ============================================================================ | |
| {-| Compile a proof term to Haskell evidence. | |
| This is a simplified version that handles basic proof terms. | |
| Full proof term handling is delegated to ProofCompiler. | |
| -} | |
| compileProofTerm :: CodeGenConfig -> Set.Set Var -> Proof -> Either String Text | |
| compileProofTerm _config _bound = \case | |
| Refl e -> Right "Refl" | |
| Symm _ -> Right "Symm" | |
| Trans _ _ -> Right "Trans" | |
| ProofVar (Var name _) -> Right name | |
| _ -> Right "()" -- Default: unit for unhandled proofs | |