Skip to content

Commit

Permalink
target type generator derivation from fused type generator added
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonTsirikov committed Jun 4, 2024
1 parent aca59a3 commit 84d7f0a
Show file tree
Hide file tree
Showing 146 changed files with 1,019 additions and 16 deletions.
91 changes: 78 additions & 13 deletions src/Deriving/DepTyCheck/Util/Fusion.idr
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Language.Reflection.TTImp
import Language.Reflection.Derive
import Language.Reflection.Pretty
import Language.Reflection.Compat
import public Deriving.DepTyCheck.Gen
import Deriving.DepTyCheck.Util.Collections
import Deriving.DepTyCheck.Util.Reflection
import Data.Nat
Expand Down Expand Up @@ -86,6 +87,7 @@ splitRhsDef [] = type
splitRhsDef (t::[]) = t
splitRhsDef (t::ts) = app (var `{Builtin.MkPair} .$ t) (splitRhsDef ts)


splitRhsClaim : List TTImp -> TTImp
splitRhsClaim [] = type
splitRhsClaim (t::[]) = t
Expand Down Expand Up @@ -114,6 +116,9 @@ record FusionDecl where
dataType : Decl
splitClaim : Decl
splitDef : Decl
genFClaim : Decl
genRClaim : Decl
genRDef : Decl


prepareConArgs : TTImp -> List TTImp
Expand All @@ -122,14 +127,29 @@ prepareConArgs t = do
map getExpr tApps


fusionTypeName : List Name -> Name
fusionTypeName = UN . Basic . (joinBy "") . (map nameStr)
joinNames : List Name -> Name
joinNames = UN . Basic . (joinBy "") . (map nameStr)


genRMkDPair : TTImp -> List Name -> TTImp
genRMkDPair = foldr (\n, acc => var `{MkDPair} .$ n.bindVar .$ acc)


genFDPair : Name -> List (Name, TTImp) -> TTImp
genFDPair n l = foldr
(\(n, tt), acc => var `{DPair} .$ tt .$ (MkArg MW ExplicitArg (Just n) tt `lam` acc))
(foldConstructor (var n) (map (var . fst) l))
l


genFRhsClaim : Name -> List (Name, TTImp) -> TTImp
genFRhsClaim n l = var `{Gen} .$ var `{MaybeEmpty} .$ genFDPair n l


deriveFusion : Vect (2 + n) (TypeInfo, List Name) -> Maybe FusionDecl
deriveFusion l = do
let typeNames = toList $ map ((.name) . fst) l
let fusionTypeName = fusionTypeName $ typeNames
let fusionTypeName = joinNames $ typeNames

let typeArgs = map (\(ti, la) => matchArgs ti.args la) l
let False = any isNothing typeArgs
Expand All @@ -146,7 +166,10 @@ deriveFusion l = do
let True = all (not . Prelude.null . fst) consPre
| False => Nothing
let consML1 = map (\(cons, args) => (toList1' cons, args)) consPre -- how to prove and use toList?
let consL1 = map (\(cons, args) => case cons of {Just x => (x, args); Nothing => ((MkCon (UN (Basic "")) [] type):::[], args)}) consML1
let consL1 = map (\(cons, args) => case cons of
Just x => (x, args)
Nothing => ((MkCon (UN (Basic "")) [] type):::[], args)
) consML1
let consAll = map (\(cons, args) => map (\c => (c, args)) cons) consL1
let consComb = combinations consAll
let consCombPrepared = map (map (\(con, args) => (con.name, prepareConArgs con.type, args))) consComb
Expand All @@ -165,17 +188,57 @@ deriveFusion l = do
splitRhsClaim (splitReturnType typeNames argNamesList)

let defDecl = if (not $ null fusedCons)
then def splitName $ splitClauses (var splitName) $ toList (map (toList . (map (nameStr . (.name) . fst))) consComb)
then def splitName $ splitClauses (var splitName) $
toList (map (toList . (map (nameStr . (.name) . fst))) consComb)
else def splitName [impossibleClause (var splitName .$ implicitTrue)]

Just (MkFusionDecl dataDecl claimDecl defDecl)
let stub = ILog Nothing
let genFName = UN $ Basic ("gen" ++ (nameStr fusionTypeName))
let genFClaim = export' genFName $
(MkArg MW ExplicitArg Nothing (var `{Fuel})) .->
(genFRhsClaim fusionTypeName uniqueArgs)

let genRClaim = export' (`{genZ_ultimate}) $
(MkArg MW ExplicitArg Nothing (var `{Fuel})) .->
(var `{Gen} .$ var `{MaybeEmpty} .$ var `{Z})

let fusedVarName = toLower $ nameStr fusionTypeName
let typeVarNames = map (toLower . nameStr) typeNames
let genRDef = def
`{genZ_ultimate}
[ var `{genZ_ultimate}
.$ bindVar "fl"
.= var `{(>>=)}
.$ (var genFName .$ var `{fl})
.$ (
MkArg MW ExplicitArg (Just "{lamc:0}") implicitFalse
`lam` iCase {
sc = var "{lamc:0}",
ty = implicitFalse,
clauses =
[ genRMkDPair (bindVar fusedVarName) uniqueNames
.= iCase {
sc = var splitName .$ (var $ UN $ Basic fusedVarName),
ty = implicitTrue,
clauses =
[ (splitRhsDef (map bindVar typeVarNames))
.= var `{pure}
.$ foldConstructor (var `{MkZ}) (map var uniqueNames ++ map (var . UN . Basic) typeVarNames)
]
}
]
}
)
]

Just (MkFusionDecl dataDecl claimDecl defDecl genFClaim genRClaim genRDef)


declareFusion : Vect (2 + n) (TypeInfo, List Name) -> Elab (Maybe FusionDecl)
declareFusion l = do
let derived = deriveFusion l
case derived of
Just fd => declare [fd.dataType, fd.splitClaim, fd.splitDef]
Just fd => declare [fd.dataType, fd.splitClaim, fd.splitDef, fd.genFClaim, fd.genRClaim, fd.genRDef]
Nothing => declare []
pure $ derived

Expand All @@ -193,11 +256,13 @@ public export
solveDependencies : List Arg -> List (List (Name, List String))
solveDependencies l = go l [] where
go : List Arg -> List (List (Name, List String)) -> List (List (Name, List String))
go [] acc = map reverse acc
go [] acc = map reverse acc -- SnocList
go (a::as) acc = go as (merge (prepareArgsSolve a) acc) where
merge : (Name, List String) -> List (List (Name, List String)) -> List (List (Name, List String))
merge a [] = [[a]]
merge (m, as) (rs::rss) = if (any (not . Prelude.null . (intersect as) . snd) rs) then ((m, as)::rs)::rss else rs::(merge (m, as) rss)
merge (m, as) (rs::rss) = if (any (not . Prelude.null . (intersect as) . snd) rs)
then ((m, as)::rs)::rss
else rs::(merge (m, as) rss)


public export
Expand Down Expand Up @@ -228,7 +293,7 @@ getSplit Nothing = []
getSplit (Just fd) = [fd.splitClaim, fd.splitDef]


-- TODO: what happens with :doc
-- tests for order of dependent arguments
-- preserve order of args from left to right
-- TODO: List Arg -> group and filter which to fuse (argDeps)
public export
getGen : Maybe FusionDecl -> List Decl
getGen Nothing = []
getGen (Just fd) = [fd.genFClaim, fd.genRClaim, fd.genRDef]
6 changes: 3 additions & 3 deletions tests/Tests.idr
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ main = goldenRunner $
, "Derivation utils: canonic signature" `atDir` "derivation/utils/canonicsig"
, "Derivation utils: constructors analysis" `atDir` "derivation/utils/cons-analysis"
, "Derivation utils: argument dependencies" `atDir` "derivation/utils/arg-deps"
, "Derivation utils: data types fusion" `atDir` "derivation/utils/fusion/merger"
, "Derivation utils: fused data types split" `atDir` "derivation/utils/fusion/splitter"
, "Derivation utils: dependency solver for fusion" `atDir` "derivation/utils/fusion/depsolver"
, [ "Derivation utils: \{p} fusion \{w}" `atDir` "derivation/utils/fusion/\{p}/\{w}"
| p <- ["print", "run"], w <- ["merger", "splitter", "depsolver", "generator"]
]
, "Reflection utils: involved types" `atDir` "derivation/utils/involved-types"
, "Derivation: input validation" `atDir` "derivation/inputvalidation"
, "Derivation: running harness" `atDir` "derivation/infra"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module DerivedGen

import public Deriving.DepTyCheck.Util.Fusion
import public Deriving.DepTyCheck.Gen.Core

%default total

data X : Type -> Type where
MkX : X n

data Y : Type -> Type where
MkY : Y n

data Z : Type where
MkZ : (n : Type) -> X n -> Y n -> Z

%language ElabReflection

decl : Maybe FusionDecl
decl = %runElab runFusion `{X} [`{n}] `{Y} [`{n}]

main : IO ()
main = putPretty $ getGen decl
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
1/1: Building DerivedGen (DerivedGen.idr)
[ IClaim
emptyFC
MW
Export
[]
(mkTy
{ name = "genXY"
, type =
MkArg MW ExplicitArg Nothing (var "Fuel")
.-> var "Gen"
.$ var "MaybeEmpty"
.$ ( var "DPair"
.$ type
.$ ( MkArg MW ExplicitArg (Just "n") type
.=> var "XY" .$ var "n"))
})
, IClaim
emptyFC
MW
Export
[]
(mkTy
{ name = "genZ_ultimate"
, type =
MkArg MW ExplicitArg Nothing (var "Fuel")
.-> var "Gen" .$ var "MaybeEmpty" .$ var "Z"
})
, IDef
emptyFC
"genZ_ultimate"
[ var "genZ_ultimate" .$ bindVar "fl"
.= var ">>="
.$ (var "genXY" .$ var "fl")
.$ ( MkArg MW ExplicitArg (Just "{lamc:0}") implicitFalse
.=> iCase
{ sc = var "{lamc:0}"
, ty = implicitFalse
, clauses =
[ var "MkDPair" .$ bindVar "n" .$ bindVar "xy"
.= iCase
{ sc = var "splitXY" .$ var "xy"
, ty = implicitTrue
, clauses =
[ var "Builtin.MkPair"
.$ bindVar "x"
.$ bindVar "y"
.= var "pure"
.$ ( var "MkZ"
.$ var "n"
.$ var "x"
.$ var "y")
]
}
]
})
]
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module DerivedGen

import public Deriving.DepTyCheck.Util.Fusion
import public Deriving.DepTyCheck.Gen.Core


%default total

data X : Type -> Type -> Type where
MkX : X m n

data Y : Type -> Type -> Type where
MkY : Y m n

data Z : Type where
MkZ : (m : Type) -> (n : Type) -> X m n -> Y m n -> Z

%language ElabReflection


decl : Maybe FusionDecl
decl = %runElab runFusion `{X} [`{m}, `{n}] `{Y} [`{m}, `{n}]

main : IO ()
main = putPretty $ getGen decl

Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
1/1: Building DerivedGen (DerivedGen.idr)
[ IClaim
emptyFC
MW
Export
[]
(mkTy
{ name = "genXY"
, type =
MkArg MW ExplicitArg Nothing (var "Fuel")
.-> var "Gen"
.$ var "MaybeEmpty"
.$ ( var "DPair"
.$ type
.$ ( MkArg MW ExplicitArg (Just "m") type
.=> var "DPair"
.$ type
.$ ( MkArg MW ExplicitArg (Just "n") type
.=> var "XY" .$ var "m" .$ var "n")))
})
, IClaim
emptyFC
MW
Export
[]
(mkTy
{ name = "genZ_ultimate"
, type =
MkArg MW ExplicitArg Nothing (var "Fuel")
.-> var "Gen" .$ var "MaybeEmpty" .$ var "Z"
})
, IDef
emptyFC
"genZ_ultimate"
[ var "genZ_ultimate" .$ bindVar "fl"
.= var ">>="
.$ (var "genXY" .$ var "fl")
.$ ( MkArg MW ExplicitArg (Just "{lamc:0}") implicitFalse
.=> iCase
{ sc = var "{lamc:0}"
, ty = implicitFalse
, clauses =
[ var "MkDPair"
.$ bindVar "m"
.$ (var "MkDPair" .$ bindVar "n" .$ bindVar "xy")
.= iCase
{ sc = var "splitXY" .$ var "xy"
, ty = implicitTrue
, clauses =
[ var "Builtin.MkPair"
.$ bindVar "x"
.$ bindVar "y"
.= var "pure"
.$ ( var "MkZ"
.$ var "m"
.$ var "n"
.$ var "x"
.$ var "y")
]
}
]
})
]
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module DerivedGen

import public Deriving.DepTyCheck.Util.Fusion
import public Deriving.DepTyCheck.Gen.Core


%default total

data X : Type -> Type -> Type where
MkX : X m n

data Y : Type -> Type -> Type where
MkY : Y m n

data Z : Type where
MkZ : (m : Type) -> (n : Type) -> X m n -> Y n m -> Z

%language ElabReflection

decl : Maybe FusionDecl
decl = %runElab runFusion `{X} [`{m}, `{n}] `{Y} [`{n}, `{m}]

main : IO ()
main = putPretty $ getGen decl
Loading

0 comments on commit 84d7f0a

Please sign in to comment.