WIP: large-anon & cleanups

This commit is contained in:
sheaf 2022-01-30 22:40:59 +01:00
parent 8333f69dc2
commit e2e5296bd1
25 changed files with 1017 additions and 1111 deletions

View file

@ -36,7 +36,7 @@ common common
, acts , acts
^>= 0.3.1.0 ^>= 0.3.1.0
, containers , containers
>= 0.6.0.1 && < 0.6.5 >= 0.6.0.1 && < 0.7
, deepseq , deepseq
>= 1.4.4.0 && < 1.5 >= 1.4.4.0 && < 1.5
, generic-data , generic-data
@ -143,14 +143,16 @@ executable MetaBrush
, MetaBrush.Document.SubdivideStroke , MetaBrush.Document.SubdivideStroke
, MetaBrush.Document.Update , MetaBrush.Document.Update
, MetaBrush.Event , MetaBrush.Event
, MetaBrush.MetaParameter.AST , MetaBrush.DSL.AST
, MetaBrush.MetaParameter.Driver , MetaBrush.DSL.Driver
, MetaBrush.MetaParameter.Eval , MetaBrush.DSL.Eval
, MetaBrush.MetaParameter.Interpolation , MetaBrush.DSL.Interpolation
, MetaBrush.MetaParameter.Parse , MetaBrush.DSL.Parse
, MetaBrush.MetaParameter.PrimOp , MetaBrush.DSL.PrimOp
, MetaBrush.MetaParameter.Rename , MetaBrush.DSL.Rename
, MetaBrush.MetaParameter.TypeCheck , MetaBrush.DSL.Types
, MetaBrush.DSL.TypeCheck
, MetaBrush.Records
, MetaBrush.Render.Document , MetaBrush.Render.Document
, MetaBrush.Render.Rulers , MetaBrush.Render.Rulers
, MetaBrush.Time , MetaBrush.Time
@ -210,9 +212,11 @@ executable MetaBrush
, hashable , hashable
^>= 1.3.0.0 ^>= 1.3.0.0
, haskell-gi , haskell-gi
>= 0.25 && < 0.26 >= 0.25 && < 0.27
, haskell-gi-base , haskell-gi-base
>= 0.25 && < 0.26 >= 0.25 && < 0.27
, large-anon
>= 0.1.0.0 && < 0.2
, lens , lens
>= 4.19.2 && < 5.1 >= 4.19.2 && < 5.1
, mtl , mtl
@ -221,15 +225,21 @@ executable MetaBrush
^>= 0.3.6.2 ^>= 0.3.6.2
, stm , stm
^>= 2.5.0.0 ^>= 2.5.0.0
, superrecord
^>= 0.5.1.0
, tardis , tardis
>= 0.4.2.0 && < 0.5 >= 0.4.2.0 && < 0.5
, text , text
>= 1.2.3.1 && < 1.2.5 >= 1.2.3.1 && < 1.3
, tree-view , tree-view
^>= 0.5 ^>= 0.5
, unordered-containers , unordered-containers
>= 0.2.11 && < 0.2.14 >= 0.2.11 && < 0.2.14
, waargonaut , waargonaut
^>= 0.8.0.2 ^>= 0.8.0.2
-- Because of large-anon:
, large-generics
>= 0.1.0.0 && < 0.2
, record-hasfield
^>= 1.0
, sop-core
^>= 0.5.0.2

View file

@ -41,8 +41,8 @@ source-repository-package
location: https://github.com/sheaf/generic-lens location: https://github.com/sheaf/generic-lens
tag: 8d3f0b405894ecade5821c99dcde6efb4a637363 tag: 8d3f0b405894ecade5821c99dcde6efb4a637363
-- superrecord API improvements
source-repository-package source-repository-package
type: git type: git
location: https://github.com/agrafix/superrecord location: https://github.com/well-typed/large-records
tag: f1c8cf87fd25243e715fd9585e595a90fff34050 subdir: large-generics
tag: acb837a9a4c22cea1abf552b47f9d3bf5af2fbdf

View file

@ -8,7 +8,8 @@
{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE RecursiveDo #-} {-# LANGUAGE RecursiveDo #-}
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -fplugin=Data.Record.Anonymous.Plugin #-}
module MetaBrush.Application module MetaBrush.Application
( runApplication ) ( runApplication )
@ -66,6 +67,12 @@ import qualified GI.GLib as GLib
-- gi-gtk -- gi-gtk
import qualified GI.Gtk as GTK import qualified GI.Gtk as GTK
-- large-anon
import Data.Record.Anonymous
( I(..) )
import qualified Data.Record.Anonymous as Rec
( empty, insert )
-- lens -- lens
import Control.Lens import Control.Lens
( (.~) ) ( (.~) )
@ -76,12 +83,6 @@ import qualified Control.Concurrent.STM as STM
import qualified Control.Concurrent.STM.TVar as STM import qualified Control.Concurrent.STM.TVar as STM
( newTVarIO, readTVar, writeTVar ) ( newTVarIO, readTVar, writeTVar )
-- superrecord
import qualified SuperRecord as Super
( Rec )
import qualified SuperRecord
( (:=)(..), (&), rnil )
-- text -- text
import qualified Data.Text as Text import qualified Data.Text as Text
( pack ) ( pack )
@ -107,8 +108,6 @@ import MetaBrush.Asset.Colours
( getColours ) ( getColours )
import MetaBrush.Asset.Logo import MetaBrush.Asset.Logo
( drawLogo ) ( drawLogo )
import MetaBrush.Brush
( adaptBrush )
import MetaBrush.Context import MetaBrush.Context
( UIElements(..), Variables(..) ( UIElements(..), Variables(..)
, Modifier(..) , Modifier(..)
@ -125,6 +124,8 @@ import MetaBrush.Document.Update
( activeDocument, withActiveDocument ) ( activeDocument, withActiveDocument )
import MetaBrush.Event import MetaBrush.Event
( handleEvents ) ( handleEvents )
import MetaBrush.Records
( Rec )
import MetaBrush.Render.Document import MetaBrush.Render.Document
( blankRender, getDocumentRender ) ( blankRender, getDocumentRender )
import MetaBrush.Render.Rulers import MetaBrush.Render.Rulers
@ -171,7 +172,7 @@ runApplication application = do
let let
testDocuments :: Map Unique DocumentHistory testDocuments :: Map Unique DocumentHistory
testDocuments = fmap newHistory $ uniqueMapFromList testDocuments = newHistory <$> uniqueMapFromList
[ emptyDocument "Test" docUnique [ emptyDocument "Test" docUnique
& ( field' @"documentContent" . field' @"strokes" ) .~ & ( field' @"documentContent" . field' @"strokes" ) .~
( Seq.fromList ( Seq.fromList
@ -179,7 +180,7 @@ runApplication application = do
{ strokeName = "Stroke 1" { strokeName = "Stroke 1"
, strokeVisible = True , strokeVisible = True
, strokeUnique = strokeUnique , strokeUnique = strokeUnique
, strokeBrush = Just $ adaptBrush @Asset.Brushes.EllipseBrushFields ellipseBrush , strokeBrush = Just ellipseBrush
, strokeSpline = , strokeSpline =
Spline Spline
{ splineStart = mkPoint ( Point2D 10 -20 ) 2 1 0 { splineStart = mkPoint ( Point2D 10 -20 ) 2 1 0
@ -194,9 +195,9 @@ runApplication application = do
) )
] ]
where where
mkPoint :: Point2D Double -> Double -> Double -> Double -> PointData ( Super.Rec Asset.Brushes.EllipseBrushFields ) mkPoint :: Point2D Double -> Double -> Double -> Double -> PointData ( Rec Asset.Brushes.EllipseBrushFields )
mkPoint pt a b phi = PointData pt Normal mkPoint pt a b phi = PointData pt Normal
( #a SuperRecord.:= a SuperRecord.& #b SuperRecord.:= b SuperRecord.& #phi SuperRecord.:= phi SuperRecord.& SuperRecord.rnil ) ( Rec.insert #a (I a) $ Rec.insert #b (I b) $ Rec.insert #phi (I phi) $ Rec.empty )
recomputeStrokesTVar <- STM.newTVarIO @Bool False recomputeStrokesTVar <- STM.newTVarIO @Bool False
documentRenderTVar <- STM.newTVarIO @( ( Int32, Int32 ) -> Cairo.Render () ) ( const $ pure () ) documentRenderTVar <- STM.newTVarIO @( ( Int32, Int32 ) -> Cairo.Render () ) ( const $ pure () )
@ -460,7 +461,7 @@ runApplication application = do
--------------------------------------------------------- ---------------------------------------------------------
-- Finishing up -- Finishing up
mbDoc <- fmap present <$> ( STM.atomically $ activeDocument variables ) mbDoc <- fmap present <$> STM.atomically ( activeDocument variables )
updateInfoBar viewportDrawingArea infoBar variables mbDoc -- need to update the info bar after widgets have been realized updateInfoBar viewportDrawingArea infoBar variables mbDoc -- need to update the info bar after widgets have been realized
GTK.widgetShow window GTK.widgetShow window

View file

@ -14,9 +14,8 @@ import Data.Kind
( Type ) ( Type )
import Data.Type.Equality import Data.Type.Equality
( (:~:)(Refl) ) ( (:~:)(Refl) )
import GHC.TypeLits
-- superrecord ( Symbol )
import qualified SuperRecord
-- text -- text
import Data.Text import Data.Text
@ -26,11 +25,11 @@ import qualified Data.Text as Text
-- MetaBrush -- MetaBrush
import MetaBrush.Brush import MetaBrush.Brush
( Brush(..) ) ( Brush(..), BrushFunction )
import MetaBrush.MetaParameter.AST import MetaBrush.DSL.Types
( BrushFunction, STypesI(..), eqTys ( STypesI(..), eqTys
) )
import MetaBrush.MetaParameter.Driver import MetaBrush.DSL.Driver
( SomeBrushFunction(..) ( SomeBrushFunction(..)
, interpretBrush , interpretBrush
) )
@ -39,7 +38,7 @@ import MetaBrush.Unique
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
type CircleBrushFields = '[ "r" SuperRecord.:= Double ] type CircleBrushFields = '[ '("r", Double) ]
circle :: UniqueSupply -> IO ( Brush CircleBrushFields ) circle :: UniqueSupply -> IO ( Brush CircleBrushFields )
circle uniqueSupply = mkBrush @CircleBrushFields uniqueSupply name code circle uniqueSupply = mkBrush @CircleBrushFields uniqueSupply name code
@ -75,7 +74,7 @@ circleCW uniqueSupply = mkBrush @CircleBrushFields uniqueSupply name code
\ -- (-r , r*c) -- (-r*c, r ) -> ( 0, r)\n\ \ -- (-r , r*c) -- (-r*c, r ) -> ( 0, r)\n\
\ -- ( r*c, r ) -- ( r , r*c) -> . ]" \ -- ( r*c, r ) -- ( r , r*c) -> . ]"
type EllipseBrushFields = '[ "a" SuperRecord.:= Double, "b" SuperRecord.:= Double, "phi" SuperRecord.:= Double ] type EllipseBrushFields = '[ '("a", Double), '("b", Double), '("phi", Double) ]
ellipse :: UniqueSupply -> IO ( Brush EllipseBrushFields ) ellipse :: UniqueSupply -> IO ( Brush EllipseBrushFields )
ellipse uniqueSupply = mkBrush @EllipseBrushFields uniqueSupply name code ellipse uniqueSupply = mkBrush @EllipseBrushFields uniqueSupply name code
@ -134,7 +133,7 @@ rounded uniqueSupply = mkBrush @roundedBrushFields uniqueSupply name code
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
mkBrush mkBrush
:: forall ( givenBrushFields :: [ Type ] ) :: forall ( givenBrushFields :: [ ( Symbol, Type ) ] )
. STypesI givenBrushFields . STypesI givenBrushFields
=> UniqueSupply -> Text -> Text => UniqueSupply -> Text -> Text
-> IO ( Brush givenBrushFields ) -> IO ( Brush givenBrushFields )

View file

@ -1,4 +1,5 @@
{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
@ -7,6 +8,7 @@
{-# LANGUAGE MagicHash #-} {-# LANGUAGE MagicHash #-}
{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE PolyKinds #-} {-# LANGUAGE PolyKinds #-}
{-# LANGUAGE QuantifiedConstraints#-}
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeOperators #-}
@ -15,86 +17,65 @@
module MetaBrush.Brush module MetaBrush.Brush
( Brush(..), SomeBrush(..) ( Brush(..), SomeBrush(..)
, BrushAdaptedTo(..), adaptBrush , BrushFunction
, SomeBrushFields(..), SomeFieldSType(..), reflectBrushFieldsNoDups , SomeFieldSType(..), SomeBrushFields(..)
, reflectBrushFieldsNoDups
) )
where where
-- base -- base
import Data.Kind import Control.Arrow
( Type ) ( (***), second )
import Data.List
( intersect )
import Data.Proxy
( Proxy )
import Data.Type.Equality
( (:~:)(Refl) )
import GHC.Exts import GHC.Exts
( Proxy#, proxy# ) ( Proxy#, Any )
import GHC.TypeLits
( KnownSymbol, SomeSymbol(..)
, someSymbolVal, symbolVal'
)
import GHC.TypeNats
( KnownNat, SomeNat(..), someNatVal, type (-) )
import Unsafe.Coerce import Unsafe.Coerce
( unsafeCoerce ) ( unsafeCoerce )
-- containers
import qualified Data.Map.Strict as Map
( fromList )
-- deepseq -- deepseq
import Control.DeepSeq import Control.DeepSeq
( NFData(..), deepseq ) ( NFData(..), deepseq )
-- groups
import Data.Group
( Group )
-- hashable -- hashable
import Data.Hashable import Data.Hashable
( Hashable(..) ) ( Hashable(..) )
-- superrecord -- large-anon
import qualified SuperRecord as Super import Data.Record.Anonymous
( Rec ) ( RecordDicts, Dict(..) )
import qualified SuperRecord import qualified Data.Record.Anonymous as Rec
( Has, RecTy, (:=) ( map )
, RecSize, RecApply(..), RecVecIdxPos, UnsafeRecBuild(..) import Data.Record.Anonymous.Internal
, TraversalCHelper, RemoveAccessTo, Intersect ( Record(MkR) )
)
import SuperRecord
( ConstC, Tuple22C )
-- text -- text
import Data.Text import Data.Text
( Text ) ( Text )
import qualified Data.Text as Text import qualified Data.Text as Text
( pack, unpack ) ( unpack )
-- unordered-containers
import Data.HashMap.Strict
( HashMap )
import qualified Data.HashMap.Strict as HashMap
( fromList, lookup )
-- MetaBrush -- MetaBrush
import Math.Module import Math.Bezier.Spline
( Module ) ( SplineType(Closed), SplinePts)
import Math.Vector2D
( Point2D )
import {-# SOURCE #-} MetaBrush.Document.Serialise import {-# SOURCE #-} MetaBrush.Document.Serialise
( Serialisable, Workaround(..), workaround ) ( Serialisable )
import MetaBrush.MetaParameter.AST import MetaBrush.DSL.Types
( SType(..), STypeI(..), SomeSType(..), STypes(..), STypesI(..), someSTypes ( STypeI, STypesI(sTypesI)
, Adapted, BrushFunction , SomeSType(..), proveSomeSTypes
, MapFields, UniqueField, UseFieldsInBrush )
import MetaBrush.DSL.Interpolation
( Interpolatable(..) )
import MetaBrush.Records
( Rec, WithParams(..)
, proveRecordDicts
) )
import MetaBrush.MetaParameter.Interpolation
( Interpolatable(..), MapDiff, HasDiff', HasTorsor )
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
whatever :: Int type BrushFunction brushFields = WithParams brushFields (SplinePts Closed)
whatever = case workaround Workaround of
Workaround -> 0
data Brush brushFields where data Brush brushFields where
BrushData BrushData
@ -103,12 +84,15 @@ data Brush brushFields where
=> =>
{ brushName :: !Text { brushName :: !Text
, brushCode :: !Text , brushCode :: !Text
, brushFunction :: !( BrushFunction brushFields ) , brushFunction :: BrushFunction brushFields
} }
-> Brush brushFields -> Brush brushFields
data SomeBrush where data SomeBrush where
SomeBrush :: !( Brush brushFields ) -> SomeBrush SomeBrush
:: STypesI brushFields
=> { someBrush :: !( Brush brushFields ) }
-> SomeBrush
instance Show ( Brush brushFields ) where instance Show ( Brush brushFields ) where
show ( BrushData { brushName, brushCode } ) = show ( BrushData { brushName, brushCode } ) =
@ -128,249 +112,62 @@ instance Hashable ( Brush brushFields ) where
hashWithSalt salt ( BrushData { brushName, brushCode } ) = hashWithSalt salt ( BrushData { brushName, brushCode } ) =
hashWithSalt ( hashWithSalt salt brushName ) brushCode hashWithSalt ( hashWithSalt salt brushName ) brushCode
data BrushAdaptedTo pointFields where
AdaptedBrush
:: forall brushFields pointFields usedFields brushParams usedParams
. ( brushParams ~ Super.Rec brushFields, STypesI brushFields
, usedParams ~ Super.Rec usedFields
, Interpolatable usedParams
, Adapted brushFields pointFields usedFields
)
=> !( Brush brushFields )
-> BrushAdaptedTo pointFields
instance Show ( BrushAdaptedTo pointFields ) where
show ( AdaptedBrush ( brush :: Brush brushFields ) ) =
"AdaptedBrush @(" <> show ( sTypesI @brushFields ) <> ") " <> show brush
instance NFData ( BrushAdaptedTo pointFields ) where
rnf ( AdaptedBrush brush ) = rnf brush
adaptBrush
:: forall pointFields brushFields
. ( STypesI brushFields, STypesI pointFields )
=> Brush brushFields
-> BrushAdaptedTo pointFields
adaptBrush brush = case proveAdapted @brushFields @pointFields of
Dict -> AdaptedBrush brush
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Instance dictionary passing machinery. -- Instance dictionary passing machinery.
data Dict c where
Dict :: c => Dict c
proveAdapted
:: forall brushFields givenFields usedFields drts_used
. ( STypesI brushFields, STypesI givenFields
, usedFields ~ ( brushFields `SuperRecord.Intersect` givenFields )
, drts_used ~ MapDiff usedFields
)
=> Dict ( Adapted brushFields givenFields usedFields
, Interpolatable ( Super.Rec usedFields )
)
proveAdapted = case go ( sTypesI @brushFields ) of { Dict -> Dict }
where
brushFields, givenFields, usedFields :: [ ( Text, SomeSType ) ]
brushFields = someSTypes @brushFields
givenFields = someSTypes @givenFields
usedFields = intersect brushFields givenFields
nbUsedFields :: Int
nbUsedFields = length usedFields
givenIxFieldsMap, usedIxFieldsMap :: HashMap Text Int
givenIxFieldsMap = listToEndIndexMap givenFields
usedIxFieldsMap = listToEndIndexMap usedFields
go :: forall lts_brush lts_used dlts_used
. ( lts_used ~ ( lts_brush `SuperRecord.Intersect` givenFields )
, dlts_used ~ MapDiff lts_used
)
=> STypes lts_brush
-> Dict
( SuperRecord.UnsafeRecBuild usedFields lts_used ( SuperRecord.Has givenFields )
, SuperRecord.RecApply ( MapFields UniqueField brushFields ) ( MapFields UniqueField lts_brush ) ( UseFieldsInBrush usedFields )
, SuperRecord.UnsafeRecBuild drts_used dlts_used ( ConstC Monoid )
, SuperRecord.UnsafeRecBuild drts_used dlts_used ( ConstC ( Module Double ) )
, SuperRecord.RecApply drts_used dlts_used ( Tuple22C ( ConstC ( Module Double ) ) ( SuperRecord.Has drts_used ) )
, SuperRecord.RecApply drts_used dlts_used ( Tuple22C ( ConstC Semigroup ) ( SuperRecord.Has drts_used ) )
, SuperRecord.RecApply drts_used dlts_used ( Tuple22C ( ConstC Group ) ( SuperRecord.Has drts_used ) )
, SuperRecord.RecApply drts_used dlts_used ( HasDiff' usedFields )
, SuperRecord.TraversalCHelper dlts_used usedFields drts_used ( HasTorsor usedFields )
)
go STyNil
| SomeNat ( _ :: Proxy nbUsedFields ) <- someNatVal ( fromIntegral nbUsedFields )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecSize usedFields :~: nbUsedFields )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecSize drts_used :~: nbUsedFields )
= Dict
go sTyCons@STyCons
| SomeNat ( _ :: Proxy nbUsedFields ) <- someNatVal ( fromIntegral nbUsedFields )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecSize usedFields :~: nbUsedFields )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecSize drts_used :~: nbUsedFields )
, ( _ :: STypes ( ( k SuperRecord.:= v ) ': tail_lts_brush ) ) <- sTyCons
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecSize ( MapFields UniqueField brushFields ) :~: SuperRecord.RecSize brushFields )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecTy k ( MapFields UniqueField brushFields ) :~: Just ( UniqueField v ) )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RemoveAccessTo k ( MapFields UniqueField tail_lts_brush ) :~: MapFields UniqueField tail_lts_brush )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecVecIdxPos k ( MapFields UniqueField brushFields ) :~: SuperRecord.RecSize tail_lts_brush )
, let
k :: Text
k = Text.pack ( symbolVal' ( proxy# :: Proxy# k ) )
= case HashMap.lookup k usedIxFieldsMap of
Just k_used_indexFromEnd
| SomeNat ( _ :: Proxy k_used_indexFromEnd ) <- someNatVal ( fromIntegral k_used_indexFromEnd )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecVecIdxPos k lts_used :~: k_used_indexFromEnd )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecVecIdxPos k usedFields :~: k_used_indexFromEnd )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecVecIdxPos k drts_used :~: k_used_indexFromEnd )
, Just k_given_indexFromEnd <- HashMap.lookup k givenIxFieldsMap
, SomeNat ( _ :: Proxy k_given_indexFromEnd ) <- someNatVal ( fromIntegral k_given_indexFromEnd )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecVecIdxPos k givenFields :~: k_given_indexFromEnd )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecTy k lts_used :~: Just v )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecTy k usedFields :~: Just v )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecTy k givenFields :~: Just v )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecTy k drts_used :~: Just ( Diff v ) )
, ( _ :: Proxy# tail_lts_used ) <- ( proxy# :: Proxy# ( tail_lts_brush `SuperRecord.Intersect` givenFields ) )
, ( _ :: Proxy# tail_dlts_used ) <- ( proxy# :: Proxy# ( MapDiff tail_lts_used ) )
, Refl <- ( unsafeCoerce Refl :: lts_used :~: ( ( k SuperRecord.:= v ) ': tail_lts_used ) )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecSize tail_lts_used :~: ( SuperRecord.RecSize lts_used - 1 ) )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecSize tail_dlts_used :~: SuperRecord.RecSize tail_lts_used )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RemoveAccessTo k tail_dlts_used :~: tail_dlts_used )
, Just Dict <- interpolatableDict @v
-> case go ( sTypesI @tail_lts_brush ) of { Dict -> Dict }
_
| Refl <- ( unsafeCoerce Refl :: SuperRecord.RecTy k lts_used :~: Nothing )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecTy k usedFields :~: Nothing )
, Refl <- ( unsafeCoerce Refl :: lts_used :~: ( tail_lts_brush `SuperRecord.Intersect` givenFields ) )
-> case go ( sTypesI @tail_lts_brush ) of { Dict -> Dict }
interpolatableDict :: forall t. STypeI t => Maybe ( Dict ( Interpolatable t ) )
interpolatableDict =
case sTypeI @t of
STyDouble -> Just Dict
sTyPoint@STyPoint
| ( _ :: SType ( Point2D c ) ) <- sTyPoint
, STyDouble <- sTypeI @c
-> Just Dict
_ -> Nothing
listToEndIndexMap :: ( Eq k, Hashable k ) => [ ( k, v ) ] -> HashMap k Int
listToEndIndexMap kvs =
HashMap.fromList
$ zipWith ( \ ( fieldName, _ ) index -> ( fieldName, lg - index - 1 ) )
kvs
[ 0 .. ]
where
lg :: Int
lg = length kvs
-- | Reflects a list of brush fields to the type level.
--
-- Assumes the input list has no duplicate field names,
-- but they don't have to be sorted.
reflectBrushFieldsNoDups :: [ ( Text, SomeFieldSType ) ] -> SomeBrushFields
reflectBrushFieldsNoDups = fromSomeBrushFieldsList . mkBrushFieldsList
where
mkBrushFieldsList :: [ ( Text, SomeFieldSType ) ] -> SomeBrushFieldsList
mkBrushFieldsList [] = SomeBrushFieldsList NilFields
mkBrushFieldsList ( ( k, SomeFieldSType ( _ :: Proxy# v ) ) : kvs )
| SomeBrushFieldsList ( kvs_list :: BrushFieldsList kvs ) <- mkBrushFieldsList kvs
, SomeSymbol ( _ :: Proxy k ) <- someSymbolVal ( Text.unpack k )
-- deduce RecSize ( MapDiff kvs ) ~ RecSize kvs
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecSize ( MapDiff kvs ) :~: SuperRecord.RecSize kvs )
-- compute indexing into record list (with SuperRecord, the index is the number of fields remaining)
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecVecIdxPos k ( ( k SuperRecord.:= v ) : kvs ) :~: SuperRecord.RecSize kvs )
= SomeBrushFieldsList ( ConsFields ( proxy# :: Proxy# k ) ( proxy# :: Proxy# v ) kvs_list )
fromSomeBrushFieldsList :: SomeBrushFieldsList -> SomeBrushFields
fromSomeBrushFieldsList ( SomeBrushFieldsList ( kvs :: BrushFieldsList kvs ) ) = case go @kvs kvs of
SomeClassyBrushFieldsList ( _ :: Proxy# kvs ) ( _ :: Proxy# kvs ) ->
SomeBrushFields ( proxy# :: Proxy# kvs )
where
go :: forall ( rts :: [ Type ] ) ( lts :: [ Type ] )
. ( STypesI rts, KnownNat ( SuperRecord.RecSize rts ), KnownNat ( SuperRecord.RecSize ( MapDiff rts ) ) )
=> BrushFieldsList lts -> SomeClassyBrushFieldsList rts lts
go NilFields =
SomeClassyBrushFieldsList ( proxy# :: Proxy# rts ) ( proxy# :: Proxy# '[] )
go ( ConsFields ( _ :: Proxy# k ) ( _ :: Proxy# a ) kvs' )
| ( SomeClassyBrushFieldsList _ ( _ :: Proxy# lts' ) ) <- go @rts kvs'
-- Assert some facts that result from the field names being distinct:
-- - current field name does not re-occur later on
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RemoveAccessTo k lts' :~: lts' )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RemoveAccessTo k ( MapDiff lts' ) :~: MapDiff lts' )
-- - looking up the type associated with the current field name returns the current type
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecTy k rts :~: Just a )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecTy k ( MapDiff rts ) :~: Just ( Diff a ) )
-- - MapDiff preserves length
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecSize ( MapDiff lts' ) :~: SuperRecord.RecSize lts' )
-- - compute the index (which is the number of fields remaining, i.e. the indexing starts counting from 0 from the right)
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecVecIdxPos k rts :~: SuperRecord.RecSize lts' )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecVecIdxPos k ( MapDiff rts ) :~: SuperRecord.RecSize lts' )
= SomeClassyBrushFieldsList ( proxy# :: Proxy# rts ) ( proxy# :: Proxy# ( ( k SuperRecord.:= a ) ': lts' ) )
-- | Existential type over an allowed record field type used in brushes, such as Double and Point2D Double. -- | Existential type over an allowed record field type used in brushes, such as Double and Point2D Double.
data SomeFieldSType where data SomeFieldSType where
SomeFieldSType SomeFieldSType
:: ( STypeI a, Show a, NFData a, Serialisable a, Interpolatable a ) :: ( STypeI a, Show a, NFData a, Interpolatable a, Serialisable a )
=> Proxy# a -> SomeFieldSType => Proxy# a -> SomeFieldSType
data FieldSType a where
FieldSType
:: ( STypeI a, Show a, NFData a, Interpolatable a, Serialisable a )
=> Proxy# a -> FieldSType a
-- | Existential type for allowed fields of a brush record. -- | Existential type for allowed fields of a brush record.
data SomeBrushFields where data SomeBrushFields where
SomeBrushFields SomeBrushFields
:: forall kvs rec :: forall kvs rec
. ( STypesI kvs . ( STypesI kvs
, rec ~ Super.Rec kvs , rec ~ Rec kvs
, Show rec, NFData rec , Show rec, NFData rec
, Interpolatable rec
, Serialisable rec , Serialisable rec
, RecordDicts kvs Interpolatable
) )
=> Proxy# kvs -> SomeBrushFields => Proxy# kvs -> SomeBrushFields
instance Show SomeBrushFields where instance Show SomeBrushFields where
show ( SomeBrushFields ( _ :: Proxy# kvs ) ) = show ( sTypesI @kvs ) show ( SomeBrushFields ( _ :: Proxy# kvs ) ) = show ( sTypesI @kvs )
-- | Auxiliary datatype used to create a proof that record fields have the required instances. -- | Reflects a list of brush fields to the type level.
data BrushFieldsList kvs where --
NilFields :: BrushFieldsList '[] -- Assumes the input list has no duplicate field names,
ConsFields -- but they don't have to be sorted.
:: reflectBrushFieldsNoDups :: [ ( Text, SomeFieldSType ) ] -> SomeBrushFields
( KnownSymbol k reflectBrushFieldsNoDups elts =
, Show a, NFData a, Serialisable a let
, Interpolatable a mkSomeSType :: SomeFieldSType -> SomeSType
, STypesI kvs mkSomeSType (SomeFieldSType px) = SomeSType px
, KnownNat ( SuperRecord.RecSize kvs ) mkField :: SomeFieldSType -> FieldSType Any
, SuperRecord.Has ( k SuperRecord.:= a ': kvs ) k a mkField (SomeFieldSType px) = unsafeCoerce $ FieldSType px
) in
=> Proxy# k -> Proxy# a -> BrushFieldsList kvs -> BrushFieldsList ( k SuperRecord.:= a ': kvs ) proveSomeSTypes (map (second mkSomeSType) elts) \ ( px :: Proxy# kvs ) ->
let
-- | Existential type used in the process of proving that record fields have the required instances. dictsRec :: Record FieldSType kvs
data SomeBrushFieldsList where dictsRec = MkR (Map.fromList $ map (Text.unpack *** mkField) elts)
SomeBrushFieldsList showDicts :: Record (Dict Show) kvs
:: ( STypesI kvs showDicts = Rec.map ( \ ( ( FieldSType ( _ :: Proxy# a ) ) ) -> Dict @Show @a ) dictsRec
, KnownNat ( SuperRecord.RecSize kvs ) nfDataDicts :: Record (Dict NFData) kvs
, KnownNat ( SuperRecord.RecSize ( MapDiff kvs ) ) nfDataDicts = Rec.map ( \ ( ( FieldSType ( _ :: Proxy# a ) ) ) -> Dict @NFData @a ) dictsRec
) serialisableDicts :: Record (Dict Serialisable) kvs
=> BrushFieldsList kvs -> SomeBrushFieldsList serialisableDicts = Rec.map ( \ ( ( FieldSType ( _ :: Proxy# a ) ) ) -> Dict @Serialisable @a ) dictsRec
interpolatableDicts :: Record (Dict Interpolatable) kvs
-- | Type used to backtrack instance resolution in the SuperRecord library, interpolatableDicts = Rec.map ( \ ( ( FieldSType ( _ :: Proxy# a ) ) ) -> Dict @Interpolatable @a ) dictsRec
-- to witness the required typeclass instances by induction on the record fields. in
data SomeClassyBrushFieldsList rts lts where proveRecordDicts @Show showDicts $
SomeClassyBrushFieldsList proveRecordDicts @NFData nfDataDicts $
:: forall rts lts drts dlts proveRecordDicts @Serialisable serialisableDicts $
. ( drts ~ MapDiff rts proveRecordDicts @Interpolatable interpolatableDicts $
, dlts ~ MapDiff lts SomeBrushFields px
, KnownNat ( SuperRecord.RecSize rts )
, KnownNat ( SuperRecord.RecSize drts )
, SuperRecord.UnsafeRecBuild rts lts ( ConstC Serialisable )
, SuperRecord.UnsafeRecBuild drts dlts ( ConstC ( Module Double ) )
, SuperRecord.UnsafeRecBuild drts dlts ( ConstC Monoid )
, SuperRecord.RecApply rts lts ( ConstC Show )
, SuperRecord.RecApply rts lts ( ConstC NFData )
, SuperRecord.RecApply rts lts ( ConstC Serialisable )
, SuperRecord.RecApply drts dlts ( Tuple22C ( ConstC ( Module Double ) ) ( SuperRecord.Has drts ) )
, SuperRecord.RecApply drts dlts ( Tuple22C ( ConstC Semigroup ) ( SuperRecord.Has drts ) )
, SuperRecord.RecApply drts dlts ( Tuple22C ( ConstC Group ) ( SuperRecord.Has drts ) )
, SuperRecord.RecApply drts dlts ( HasDiff' rts )
, SuperRecord.TraversalCHelper dlts rts drts ( HasTorsor rts )
)
=> Proxy# rts -> Proxy# lts -> SomeClassyBrushFieldsList rts lts

View file

@ -15,53 +15,38 @@
{-# LANGUAGE RankNTypes #-} {-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilyDependencies #-} {-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
module MetaBrush.MetaParameter.AST module MetaBrush.DSL.AST
( Span(..), Located(.., Location) ( Span(..), Located(.., Location)
, Term(..), Pat(..), Decl(..) , Term(..), Pat(..), Decl(..)
, toTreeArgsTerm, toTreeTerm, toTreePat, toTreeDecl , toTreeArgsTerm, toTreeTerm, toTreePat, toTreeDecl
, termSpan , termSpan
, TypedTerm(..), TypedPat(..) , TypedTerm(..), TypedPat(..)
, SType(..), STypeI(..), SomeSType(..)
, STypes(..), STypesI(..), someSTypes
, eqSTy, eqTy, eqSTys, eqTys
, Pass(..), Name, UniqueName(..), Loc , Pass(..), Name, UniqueName(..), Loc
, Ext_With(..), X_With(..) , Ext_With(..), X_With(..)
, MapFields, IsUniqueTerm, IsUniqueTerm2, UseFieldsInBrush , UniqueField(..), UniqueTerm(..)
, UniqueField(..), GetUniqueField, UniqueTerm, GetUniqueTerm
, Adapted, AdaptableFunction(..), BrushFunction
, X_Ext(..) , X_Ext(..)
, Expr, EPat, RnExpr, RnPat , Expr, EPat, RnExpr, RnPat
) )
where where
-- base -- base
import Data.Functor.Compose
( Compose(..) )
import Data.Functor.Identity import Data.Functor.Identity
( Identity(..) ) ( Identity(..) )
import Data.Kind import Data.Kind
( Type, Constraint ) ( Type, Constraint )
import Data.List
( intercalate )
import Data.Proxy
( Proxy(..) )
import Data.Type.Equality
( (:~:)(Refl) )
import GHC.Exts
( Proxy#, proxy# )
import GHC.Generics import GHC.Generics
( Generic ) ( Generic )
import GHC.TypeLits import GHC.TypeLits
( Symbol, KnownSymbol, symbolVal', sameSymbol ) ( Symbol )
import GHC.TypeNats
( KnownNat )
-- containers -- containers
import Data.Tree import Data.Tree
@ -71,19 +56,13 @@ import Data.Tree
import Control.DeepSeq import Control.DeepSeq
( NFData(..) ) ( NFData(..) )
-- superrecord -- large-anon
import qualified SuperRecord as Super import Data.Record.Anonymous
( Rec ) ( Record )
import qualified SuperRecord
( (:=), RecApply, UnsafeRecBuild, Has, TraversalC
, Intersect, Lookup, RecTy, RecSize, reflectRec
)
-- text -- text
import Data.Text import Data.Text
( Text ) ( Text )
import qualified Data.Text as Text
( pack )
-- MetaBrush -- MetaBrush
import Math.Vector2D import Math.Vector2D
@ -93,10 +72,14 @@ import qualified Math.Bezier.Cubic as Cubic
import qualified Math.Bezier.Quadratic as Quadratic import qualified Math.Bezier.Quadratic as Quadratic
( Bezier(..) ) ( Bezier(..) )
import Math.Bezier.Spline import Math.Bezier.Spline
( Spline(..), SplinePts, SplineType(..) ( Spline(..), SplineType(..)
, SSplineType(..), SplineTypeI(ssplineType), KnownSplineType(bifoldSpline) , SSplineType(..), SplineTypeI(ssplineType), KnownSplineType(bifoldSpline)
, Curve(..), NextPoint(..) , Curve(..), NextPoint(..)
) )
import MetaBrush.DSL.Types
( STypeI(..) )
import MetaBrush.Records
( WithParams, foldRec )
import MetaBrush.Unique import MetaBrush.Unique
( Unique ) ( Unique )
@ -137,148 +120,6 @@ data Located a =
pattern Location :: Span -> Located () pattern Location :: Span -> Located ()
pattern Location loc = Located loc () pattern Location loc = Located loc ()
----------
-- Types.
data SType ( ty :: Type ) where
SFunTy :: ( STypeI a, STypeI b ) => SType ( a -> b )
STyBool :: SType Bool
STyDouble :: SType Double
STyPoint :: STypeI a => SType ( Point2D a )
STyLine :: STypeI a => SType ( Segment a )
STyBez2 :: STypeI a => SType ( Quadratic.Bezier a )
STyBez3 :: STypeI a => SType ( Cubic.Bezier a )
STySpline :: KnownSplineType clo => SType ( SplinePts clo )
STyWithFn :: ( STypesI kvs, STypeI a ) => SType ( AdaptableFunction kvs a )
-- reminder: update eqSTy when adding new constructors
deriving stock instance Show ( SType ty )
class STypeI ty where
sTypeI :: SType ty
instance ( STypeI a, STypeI b ) => STypeI ( a -> b ) where
sTypeI = SFunTy
instance STypeI Bool where
sTypeI = STyBool
instance STypeI Double where
sTypeI = STyDouble
instance STypeI a => STypeI ( Point2D a ) where
sTypeI = STyPoint
instance STypeI a => STypeI ( Segment a ) where
sTypeI = STyLine
instance STypeI a => STypeI ( Quadratic.Bezier a ) where
sTypeI = STyBez2
instance STypeI a => STypeI ( Cubic.Bezier a ) where
sTypeI = STyBez3
instance KnownSplineType clo => STypeI ( SplinePts clo ) where
sTypeI = STySpline
instance ( STypesI kvs, STypeI a ) => STypeI ( AdaptableFunction kvs a ) where
sTypeI = STyWithFn
data STypes ( kvs :: [ Type ] ) where
STyNil :: STypes '[]
STyCons :: ( kv ~ ( k SuperRecord.:= v ), KnownSymbol k, STypeI v, STypesI kvs ) => STypes ( kv ': kvs )
instance Show ( STypes kvs ) where
show sTypes = "'[" <> intercalate "," ( showSTypes sTypes ) <> "]"
showSTypes :: STypes kvs -> [ String ]
showSTypes STyNil = []
showSTypes sTyCons@STyCons
| ( _ :: STypes ( ( k SuperRecord.:= v ) ': tail_kvs ) ) <- sTyCons
= ( symbolVal' ( proxy# :: Proxy# k ) <> " := " <> show ( sTypeI @v ) ) : showSTypes ( sTypesI @tail_kvs )
class KnownNat ( SuperRecord.RecSize kvs ) => STypesI kvs where
sTypesI :: STypes kvs
instance STypesI '[] where
sTypesI = STyNil
-- Warning: this instance is somewhat overly general as it doesn't check for lack of duplicates
instance ( kv ~ ( k SuperRecord.:= v ), KnownSymbol k, STypeI v, STypesI kvs ) => STypesI ( kv ': kvs ) where
sTypesI = STyCons
data SomeSType where
SomeSType :: STypeI a => Proxy# a -> SomeSType
instance Show SomeSType where
show ( SomeSType ( _ :: Proxy# a ) ) = show ( sTypeI @a )
instance Eq SomeSType where
( SomeSType ( _ :: Proxy# a ) ) == ( SomeSType ( _ :: Proxy# b ) ) =
case eqTy @a @b of
Just _ -> True
_ -> False
eqSTy :: SType a -> SType b -> Maybe ( a :~: b )
eqSTy sTy_a@SFunTy sTy_b@SFunTy
| ( _ :: SType ( a1 -> b1 ) ) <- sTy_a
, ( _ :: SType ( a2 -> b2 ) ) <- sTy_b
, Just Refl <- eqTy @a1 @a2
, Just Refl <- eqTy @b1 @b2
= Just Refl
eqSTy STyBool STyBool = Just Refl
eqSTy STyDouble STyDouble = Just Refl
eqSTy sTy_a@STyPoint sTy_b@STyPoint
| ( _ :: SType ( Point2D l ) ) <- sTy_a
, ( _ :: SType ( Point2D r ) ) <- sTy_b
, Just Refl <- eqTy @l @r
= Just Refl
eqSTy sTy_a@STyLine sTy_b@STyLine
| ( _ :: SType ( Segment l ) ) <- sTy_a
, ( _ :: SType ( Segment r ) ) <- sTy_b
, Just Refl <- eqTy @l @r
= Just Refl
eqSTy sTy_a@STyBez2 sTy_b@STyBez2
| ( _ :: SType ( Quadratic.Bezier l ) ) <- sTy_a
, ( _ :: SType ( Quadratic.Bezier r ) ) <- sTy_b
, Just Refl <- eqTy @l @r
= Just Refl
eqSTy sTy_a@STyBez3 sTy_b@STyBez3
| ( _ :: SType ( Cubic.Bezier l ) ) <- sTy_a
, ( _ :: SType ( Cubic.Bezier r ) ) <- sTy_b
, Just Refl <- eqTy @l @r
= Just Refl
eqSTy sTy_a@STySpline sTy_b@STySpline
| ( _ :: SType ( SplinePts clo1 ) ) <- sTy_a
, ( _ :: SType ( SplinePts clo2 ) ) <- sTy_b
= case ( ssplineType @clo1, ssplineType @clo2 ) of
( SOpen , SOpen ) -> Just Refl
( SClosed, SClosed ) -> Just Refl
_ -> Nothing
eqSTy sTy_a@STyWithFn sTy_b@STyWithFn
| ( _ :: SType ( AdaptableFunction kvs a ) ) <- sTy_a
, ( _ :: SType ( AdaptableFunction lvs b ) ) <- sTy_b
, Just Refl <- eqTys @kvs @lvs
, Just Refl <- eqTy @a @b
= Just Refl
eqSTy _ _ = Nothing
eqTy :: forall a b. ( STypeI a, STypeI b ) => Maybe ( a :~: b )
eqTy = eqSTy ( sTypeI @a ) ( sTypeI @b )
eqSTys :: STypes as -> STypes bs -> Maybe ( as :~: bs )
eqSTys STyNil STyNil = Just Refl
eqSTys sTyCons1@STyCons sTyCons2@STyCons
| ( _ :: STypes ( ( l1 SuperRecord.:= v1 ) ': as' ) ) <- sTyCons1
, ( _ :: STypes ( ( l2 SuperRecord.:= v2 ) ': bs' ) ) <- sTyCons2
, Just Refl <- sameSymbol ( Proxy :: Proxy l1 ) ( Proxy :: Proxy l2 )
, Just Refl <- eqTy @v1 @v2
, Just Refl <- eqTys @as' @bs'
= Just Refl
eqSTys _ _ = Nothing
eqTys :: forall as bs. ( STypesI as, STypesI bs ) => Maybe ( as :~: bs )
eqTys = eqSTys ( sTypesI @as ) ( sTypesI @bs )
someSTypes :: forall kvs. STypesI kvs => [ ( Text, SomeSType ) ]
someSTypes = go ( sTypesI @kvs )
where
go :: forall lvs. STypes lvs -> [ ( Text, SomeSType ) ]
go STyNil = []
go sTyCons@STyCons
| ( _ :: STypes ( ( l SuperRecord.:= v ) ': lvs' ) ) <- sTyCons
, let
l :: Text
l = Text.pack $ symbolVal' ( proxy# :: Proxy# l )
= ( l, SomeSType ( proxy# :: Proxy# v ) )
: go ( sTypesI @lvs' )
------------------------------------------------ ------------------------------------------------
-- AST. -- -- AST. --
---------- ----------
@ -286,42 +127,51 @@ someSTypes = go ( sTypesI @kvs )
data Pass = P | Rn | Tc data Pass = P | Rn | Tc
deriving stock Show deriving stock Show
-- | What kind should we use for the intrinsic typing of the AST?
--
-- Parsing and renaming: no intrinsic typing, so use the unit type.
-- Typechecking: a term is typed with something of kind 'Type'.
type family K ( p :: Pass ) :: Type where type family K ( p :: Pass ) :: Type where
K P = () K P = ()
K Rn = () K Rn = ()
K Tc = Type K Tc = Type
type family Ks ( p :: Pass ) :: Type where -- | What kind should we use for the intrinsic typing of rows?
Ks P = () --
Ks Rn = () -- Parsing and renaming: no intrinsic typing, use the unit type.
Ks Tc = [Type] -- Typechecking: records use an association list @Symbol --> Type@.
type family Kvs ( p :: Pass ) :: Type where
Kvs P = ()
Kvs Rn = ()
Kvs Tc = [ ( Symbol, Type ) ]
type family T ( p :: Pass ) ( t :: Type ) :: K p where -- | Label a term with its type, depending on the pass.
type T :: forall (p :: Pass) -> Type -> K p
type family T p t where
T P _ = '() T P _ = '()
T Rn _ = '() T Rn _ = '()
T Tc a = a T Tc a = a
type family Ts ( p :: Pass ) ( as :: [ Type ] ) :: Ks p where -- | Label a record with its type, depending on the pass.
Ts P _ = '() type R :: forall (p :: Pass) -> [ ( Symbol, Type ) ] -> Kvs p
Ts Rn _ = '() type family R p kvs where
Ts Tc '[] = '[]
Ts Tc ( a ': as ) = T Tc a ': Ts Tc as
type family R ( p :: Pass ) ( kvs :: [ Type ] ) :: Ks p where
R P _ = '() R P _ = '()
R Rn _ = '() R Rn _ = '()
R Tc kvs = kvs R Tc kvs = kvs
-- | We produce evidence for constraints at the constraint solving stage;
-- before that, use the unit type to represent lack of any kind of evidence.
--
-- - @C p ct@: a constraint for which evidence is produced by the constraint solver.
-- - @ct@: a constraint for which evidence is provided at the start.
type family C ( p :: Pass ) ( ct :: Constraint ) :: Constraint where type family C ( p :: Pass ) ( ct :: Constraint ) :: Constraint where
C P _ = () C P _ = ()
C Rn _ = () C Rn _ = ()
C Tc ct = ct C Tc ct = ct
-- C p ct: constraint for which evidence is generated at Tc stage
-- ct: constraint for which evidence is provided from the start
infixl 9 :$ infixl 9 :$
data Term ( p :: Pass ) ( kind :: K p ) where type Term :: forall (p :: Pass) -> K p -> Type
data Term p kind where
(:$) :: C p ( STypeI a ) (:$) :: C p ( STypeI a )
=> Term p ( T p ( a -> b ) ) => Term p ( T p ( a -> b ) )
-> Term p ( T p a ) -> Term p ( T p a )
@ -333,13 +183,13 @@ data Term ( p :: Pass ) ( kind :: K p ) where
, let_body :: !( Term p ( T p a ) ) , let_body :: !( Term p ( T p a ) )
} }
-> Term p ( T p a ) -> Term p ( T p a )
With :: forall ( p :: Pass ) ( kvs :: [ Type ] ) ( a :: Type ) With :: forall ( p :: Pass ) ( kvs :: [ ( Symbol, Type ) ] ) ( a :: Type )
. C p ( STypeI a ) . C p ( STypeI a )
=> ![ Loc p () ] => ![ Loc p () ]
-> !( X_With p ( R p kvs ) ) -> !( X_With p ( R p kvs ) )
-> ![ Term p ( T p Bool ) ] -> ![ Term p ( T p Bool ) ]
-> !( Term p ( T p a ) ) -> !( Term p ( T p a ) )
-> Term p ( T p ( AdaptableFunction kvs a ) ) -> Term p ( T p ( WithParams kvs a ) )
Lit :: ( Show a, STypeI a ) Lit :: ( Show a, STypeI a )
=> !( Loc p ( Maybe Text ) ) => !( Loc p ( Maybe Text ) )
-> !a -> !a
@ -384,7 +234,8 @@ data Decl ( p :: Pass ) where
-> !( Term p ( T p b ) ) -> !( Term p ( T p b ) )
-> Decl p -> Decl p
data Pat ( p :: Pass ) ( kind :: K p ) where type Pat :: forall (p :: Pass) -> K p -> Type
data Pat p kind where
PName :: { patName :: !( Loc p ( Name p ) ) } PName :: { patName :: !( Loc p ( Name p ) ) }
-> Pat p ( T p a ) -> Pat p ( T p a )
PPoint :: ![ Loc p () ] PPoint :: ![ Loc p () ]
@ -429,9 +280,10 @@ type instance Name Tc = UniqueName
type family Loc ( p :: Pass ) ( a :: Type ) :: Type type family Loc ( p :: Pass ) ( a :: Type ) :: Type
type instance Loc p a = Located a type instance Loc p a = Located a
class Ext_With ( p :: Pass ) ( kvs :: Ks p ) where type Ext_With :: forall (p :: Pass) -> Kvs p -> Constraint
class Ext_With p kvs where
data family X_With p kvs :: Type data family X_With p kvs :: Type
toTreeWith :: forall ( lvs :: Ks p ). Ext_With p lvs => X_With p kvs -> [ Tree String ] toTreeWith :: forall ( lvs :: Kvs p ). Ext_With p lvs => X_With p kvs -> [ Tree String ]
instance Ext_With P kvs where instance Ext_With P kvs where
newtype X_With P _ = P_With [ Decl P ] newtype X_With P _ = P_With [ Decl P ]
@ -441,99 +293,25 @@ instance Ext_With Rn kvs where
newtype X_With Rn _ = Rn_With [ Decl Rn ] newtype X_With Rn _ = Rn_With [ Decl Rn ]
toTreeWith ( Rn_With decls ) = map toTreeDecl decls toTreeWith ( Rn_With decls ) = map toTreeDecl decls
instance Ext_With Tc kvs where instance Ext_With Tc kvs where
data X_With Tc kvs where data X_With Tc kvs where
Tc_With Tc_With :: Record UniqueTerm kvs -> X_With Tc kvs
:: ( ts ~ MapFields UniqueTerm kvs
, fs ~ MapFields UniqueField kvs
, SuperRecord.RecApply ts ts IsUniqueTerm
, SuperRecord.TraversalC IsUniqueTerm2 ts fs
)
=> Super.Rec ts -> X_With Tc kvs
toTreeWith ( Tc_With decls ) = toTreeWith ( Tc_With decls ) =
SuperRecord.reflectRec @IsUniqueTerm foldRec
( \ _ ( Compose ( UniqueField { uniqueField = a } ) ) -> toTreeTerm @Tc a ) ( \ ( UniqueTerm { uniqueTerm = a } ) rest -> toTreeTerm @Tc a : rest )
decls decls
[]
data UniqueField a = data UniqueField a where
UniqueField { uniqueFieldName :: !UniqueName, uniqueField :: !a } UniqueField
:: STypeI a
type UniqueTerm = Compose UniqueField ( Term Tc ) => { uniqueFieldName :: !UniqueName, uniqueField :: !a }
-> UniqueField a
type family MapFields ( f :: Type -> Type ) ( kvs :: [ Type ] ) = ( r :: [ Type ] ) | r -> kvs where data UniqueTerm a where
MapFields _ '[] = '[] UniqueTerm
MapFields f ( ( k SuperRecord.:= v ) ': kvs ) = ( k SuperRecord.:= f v ) ': MapFields f kvs :: STypeI a
=> { uniqueTermName :: !UniqueName, uniqueTerm :: !( Term Tc a ) }
-> UniqueTerm a
type family GetUniqueField ( uniqueField :: Type ) :: Type where
GetUniqueField ( UniqueField a ) = a
type family GetUniqueTerm ( uniqueTerm :: Type ) :: Type where
GetUniqueTerm ( Compose UniqueField ( Term Tc ) a ) = a
class ( STypeI ( GetUniqueTerm t )
, t ~ UniqueTerm ( GetUniqueTerm t )
)
=> IsUniqueTerm ( k :: Symbol ) t
where
instance ( STypeI ( GetUniqueTerm t )
, t ~ UniqueTerm ( GetUniqueTerm t )
)
=> IsUniqueTerm ( k :: Symbol ) t
where
class ( IsUniqueTerm k t
, a ~ UniqueField ( GetUniqueField a )
, GetUniqueTerm t ~ GetUniqueField a
)
=> IsUniqueTerm2 k t a
where
instance ( IsUniqueTerm k t
, a ~ UniqueField ( GetUniqueField a )
, GetUniqueTerm t ~ GetUniqueField a
)
=> IsUniqueTerm2 k t a
where
class ( STypeI ( GetUniqueField t )
, t ~ UniqueField ( GetUniqueField t )
, SuperRecord.Lookup kvs k ( GetUniqueField t )
( SuperRecord.RecTy k kvs )
)
=> UseFieldsInBrush ( kvs :: [ Type ] ) ( k :: Symbol ) t
instance ( STypeI ( GetUniqueField t )
, t ~ UniqueField ( GetUniqueField t )
, SuperRecord.Lookup kvs k ( GetUniqueField t )
( SuperRecord.RecTy k kvs )
)
=> UseFieldsInBrush ( kvs :: [ Type ] ) ( k :: Symbol ) t
class ( usedFields ~ ( brushFields `SuperRecord.Intersect` givenFields )
, SuperRecord.UnsafeRecBuild usedFields usedFields ( SuperRecord.Has givenFields )
, SuperRecord.RecApply ( MapFields UniqueField brushFields ) ( MapFields UniqueField brushFields )
( UseFieldsInBrush usedFields )
)
=> Adapted brushFields givenFields usedFields | givenFields brushFields -> usedFields
instance ( usedFields ~ ( brushFields `SuperRecord.Intersect` givenFields )
, SuperRecord.UnsafeRecBuild usedFields usedFields ( SuperRecord.Has givenFields )
, SuperRecord.RecApply ( MapFields UniqueField brushFields ) ( MapFields UniqueField brushFields )
( UseFieldsInBrush usedFields )
)
=> Adapted brushFields givenFields usedFields
type BrushFunction brushFields = AdaptableFunction brushFields ( SplinePts Closed )
newtype AdaptableFunction brushFields a
= AdaptableFunction
( forall givenFields usedFields
. ( Adapted brushFields givenFields usedFields
-- Debugging.
, Show ( Super.Rec givenFields )
)
=> ( Super.Rec givenFields -> Super.Rec usedFields
, Super.Rec usedFields -> a
)
)
class Ext ( p :: Pass ) ( a :: K p ) where class Ext ( p :: Pass ) ( a :: K p ) where
data family X_Ext ( p :: Pass ) a :: Type data family X_Ext ( p :: Pass ) a :: Type
@ -582,7 +360,7 @@ toTreeTerm = toTreeArgsTerm @p @a []
toTreeArgsTerm toTreeArgsTerm
:: forall ( p :: Pass ) ( a :: K p ) :: forall ( p :: Pass ) ( a :: K p )
. ( Show ( Name p ), forall x. Ext p x, forall (kvs :: Ks p). Ext_With p kvs ) . ( Show ( Name p ), forall x. Ext p x, forall (kvs :: Kvs p). Ext_With p kvs )
=> [ Tree String ] => [ Tree String ]
-> Term p a -> Term p a
-> Tree String -> Tree String
@ -598,12 +376,10 @@ toTreeArgsTerm as ( Line _ p0 p1 ) = Node "Line" ( toTreeTerm p0 : toTr
toTreeArgsTerm as ( Bez2 _ p0 p1 p2 ) = Node "Bez2" ( toTreeTerm p0 : toTreeTerm p1 : toTreeTerm p2 : as ) toTreeArgsTerm as ( Bez2 _ p0 p1 p2 ) = Node "Bez2" ( toTreeTerm p0 : toTreeTerm p1 : toTreeTerm p2 : as )
toTreeArgsTerm as ( Bez3 _ p0 p1 p2 p3 ) = Node "Bez3" ( toTreeTerm p0 : toTreeTerm p1 : toTreeTerm p2 : toTreeTerm p3 : as ) toTreeArgsTerm as ( Bez3 _ p0 p1 p2 p3 ) = Node "Bez3" ( toTreeTerm p0 : toTreeTerm p1 : toTreeTerm p2 : toTreeTerm p3 : as )
toTreeArgsTerm as ( PolyBez _ spline ) = Node "Spline" toTreeArgsTerm as ( PolyBez _ spline ) = Node "Spline"
( ( runIdentity ( runIdentity (( bifoldSpline @_ @Identity @[ Tree String ] @_ )
$ ( bifoldSpline @_ @Identity @[ Tree String ] @_ )
( const ( toTreeCurve @p ) ) ( const ( toTreeCurve @p ) )
( Identity . (:[]) . toTreeTerm ) ( Identity . (:[]) . toTreeTerm )
spline spline)
)
<> as <> as
) )
toTreeArgsTerm as ( Let _ ds a ) = toTreeArgsTerm as ( Let _ ds a ) =
@ -623,7 +399,7 @@ toTreeArgsTerm as ( CExt ext ) = toTreeArgsExt as ext
toTreeDecl toTreeDecl
:: forall ( p :: Pass ) :: forall ( p :: Pass )
. ( Show ( Name p ), forall x. Ext p x, forall (kvs :: Ks p). Ext_With p kvs ) . ( Show ( Name p ), forall x. Ext p x, forall (kvs :: Kvs p). Ext_With p kvs )
=> Decl p => Decl p
-> Tree String -> Tree String
toTreeDecl ( ValDecl lhs _ rhs ) = Node "(=)" [ toTreePat lhs, toTreeTerm rhs ] toTreeDecl ( ValDecl lhs _ rhs ) = Node "(=)" [ toTreePat lhs, toTreeTerm rhs ]
@ -637,7 +413,7 @@ toTreePat ( AsPat _ nm pat ) = Node "(@)" [ Node ( show nm ) [], toTreeP
toTreeCurve toTreeCurve
:: forall ( p :: Pass ) ( clo :: SplineType ) ( crvData :: Type ) ( a :: K p ) :: forall ( p :: Pass ) ( clo :: SplineType ) ( crvData :: Type ) ( a :: K p )
. ( SplineTypeI clo, Show ( Name p ), forall x. Ext p x, forall (kvs :: Ks p). Ext_With p kvs ) . ( SplineTypeI clo, Show ( Name p ), forall x. Ext p x, forall (kvs :: Kvs p). Ext_With p kvs )
=> Curve clo crvData ( Term p a ) => Curve clo crvData ( Term p a )
-> Identity [ Tree String ] -> Identity [ Tree String ]
toTreeCurve curve = Identity . (:[]) $ case ssplineType @clo of toTreeCurve curve = Identity . (:[]) $ case ssplineType @clo of

View file

@ -12,7 +12,7 @@
{-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_GHC -fno-warn-orphans #-}
module MetaBrush.MetaParameter.Driver where module MetaBrush.DSL.Driver where
-- base -- base
import GHC.Exts import GHC.Exts
@ -43,22 +43,27 @@ import Control.Monad.Trans.State.Strict
-- MetaBrush -- MetaBrush
import Math.Bezier.Spline import Math.Bezier.Spline
( SplinePts, SSplineType(SClosed), SplineTypeI(ssplineType) ) ( SplinePts, SSplineType(SClosed), SplineTypeI(ssplineType) )
import MetaBrush.MetaParameter.AST import MetaBrush.Brush
( BrushFunction )
import MetaBrush.DSL.AST
( Located ( Located
, Term, TypedTerm(..) , Term, TypedTerm(..)
, SType(..), STypeI(sTypeI)
, SomeSType(..), STypesI
, Pass(Tc) , Pass(Tc)
, AdaptableFunction(..), BrushFunction
) )
import MetaBrush.MetaParameter.Eval import MetaBrush.DSL.Types
( SType(..), STypeI(sTypeI)
, SomeSType(..), STypesI
)
import MetaBrush.DSL.Eval
( EvalState(..), eval ) ( EvalState(..), eval )
import MetaBrush.MetaParameter.Parse import MetaBrush.DSL.Parse
( grammar, Token, tokenize ) ( grammar, Token, tokenize )
import MetaBrush.MetaParameter.Rename import MetaBrush.DSL.Rename
( rename, RnM, RnMessage, RnError, emptyRnState ) ( rename, RnM, RnMessage, RnError, emptyRnState )
import MetaBrush.MetaParameter.TypeCheck import MetaBrush.DSL.TypeCheck
( typeCheck, TcM, TcMessage, TcError, emptyTcState ) ( typeCheck, TcM, TcMessage, TcError, emptyTcState )
import MetaBrush.Records
( WithParams )
import MetaBrush.Unique import MetaBrush.Unique
( UniqueSupply, MonadUnique(freshUnique) ) ( UniqueSupply, MonadUnique(freshUnique) )
@ -133,7 +138,7 @@ interpretBrush uniqSupply sourceText = case Earley.fullParses ( Earley.parser gr
-- a closed brush shape. -- a closed brush shape.
Right ( TypedTerm ( term :: Term Tc v ) ) Right ( TypedTerm ( term :: Term Tc v ) )
| sTyWithFn@STyWithFn <- sTypeI @v | sTyWithFn@STyWithFn <- sTypeI @v
, ( _ :: SType ( AdaptableFunction kvs b ) ) <- sTyWithFn , ( _ :: SType ( WithParams kvs b ) ) <- sTyWithFn
, sTySpline@STySpline <- sTypeI @b , sTySpline@STySpline <- sTypeI @b
, ( _ :: SType ( SplinePts clo ) ) <- sTySpline , ( _ :: SType ( SplinePts clo ) ) <- sTySpline
, SClosed <- ssplineType @clo , SClosed <- ssplineType @clo

View file

@ -15,15 +15,13 @@
{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableInstances #-}
module MetaBrush.MetaParameter.Eval module MetaBrush.DSL.Eval
( EvalState(..), eval ) ( EvalState(..), eval )
where where
-- base -- base
import Data.Foldable import Data.Foldable
( for_, traverse_ ) ( for_, traverse_ )
import Data.Functor.Compose
( Compose(..) )
import Data.Type.Equality import Data.Type.Equality
( (:~:)(Refl) ) ( (:~:)(Refl) )
import GHC.Generics import GHC.Generics
@ -39,6 +37,11 @@ import qualified Data.Map.Strict as Map
import Data.Generics.Product.Fields import Data.Generics.Product.Fields
( field' ) ( field' )
-- large-anon
import Data.Record.Anonymous
( Record, I(..) )
import qualified Data.Record.Anonymous as Rec
-- lens -- lens
import Control.Lens import Control.Lens
( assign, modifying, use ) ( assign, modifying, use )
@ -47,12 +50,6 @@ import Control.Lens
import Control.Monad.State import Control.Monad.State
( get ) ( get )
-- superrecord
import qualified SuperRecord as Super
( Rec )
import qualified SuperRecord
( RecApply(..), Lookup(..), Has, UnsafeRecBuild, traverseC, project )
-- text -- text
import Data.Text import Data.Text
( Text ) ( Text )
@ -72,17 +69,23 @@ import Math.Bezier.Spline
( KnownSplineType(bitraverseSpline), bitraverseCurve ) ( KnownSplineType(bitraverseSpline), bitraverseCurve )
import Math.Vector2D import Math.Vector2D
( Point2D(..), Segment(..) ) ( Point2D(..), Segment(..) )
import MetaBrush.MetaParameter.AST import MetaBrush.DSL.AST
( Term(..), Pat(..), Decl(..) ( Term(..), Pat(..), Decl(..)
, TypedTerm(..), STypeI(..), SType(..) , TypedTerm(..)
, Pass(Tc), X_Ext(..), X_With(..) , Pass(Tc), X_Ext(..), X_With(..)
, Span(..), Located(..) , Span(..), Located(..)
, MapFields, AdaptableFunction(..) , UniqueField(..), UniqueTerm(..)
, UniqueField(..), UniqueTerm, IsUniqueTerm2, UseFieldsInBrush )
import MetaBrush.DSL.Types
( STypeI(..), SType(..)
, eqTy , eqTy
) )
import MetaBrush.MetaParameter.Rename import MetaBrush.DSL.Rename
( UniqueName(..) ) ( UniqueName(..) )
import MetaBrush.Records
( Rec, WithParams(..)
, foldRec
)
import MetaBrush.Unique import MetaBrush.Unique
( Unique ) ( Unique )
@ -109,33 +112,45 @@ eval ( PolyBez _ spline ) =
eval eval
spline spline
eval ( Let _ decls a ) = traverse_ declare decls *> eval a eval ( Let _ decls a ) = traverse_ declare decls *> eval a
eval ( With _ ( Tc_With ( withDeclsRecord :: Super.Rec ( MapFields UniqueTerm brushFields ) ) ) _ ( body :: Term Tc r ) ) = do eval ( With _ ( Tc_With ( withDeclsRecord :: Record UniqueTerm brushFields ) ) _ ( body :: Term Tc r ) ) = do
defaultParamsRecord <-
SuperRecord.traverseC @IsUniqueTerm2 @( State EvalState ) @( MapFields UniqueTerm brushFields ) @( MapFields UniqueField brushFields ) -- Evaluate the default parameter values for the brush.
( \ _ ( Compose ( UniqueField uniq term ) ) -> UniqueField uniq <$> eval term ) ( defaultParamsRecord :: Record UniqueField brushFields ) <-
Rec.mapM
( \ ( UniqueTerm uniq term ) -> do
val <- eval term
return $ UniqueField uniq val
)
withDeclsRecord withDeclsRecord
-- Interpretation: compute the brush function by binding
-- the provided values.
EvalState { evalHeap, nextUnique } <- get EvalState { evalHeap, nextUnique } <- get
let let
toBrushParameters brushFunction :: Rec brushFields -> r
:: forall givenFields usedFields brushFunction brushParams =
. ( SuperRecord.UnsafeRecBuild usedFields usedFields -- We will receive a record of parameters that will
( SuperRecord.Has givenFields ) -- have been obtained by an intersection followed by
) -- an embedding:
=> Super.Rec givenFields -> Super.Rec usedFields --
toBrushParameters = SuperRecord.project -- Rec (givenFields /\ brushFields) -> Rec brushFields
brushFunction --
:: forall usedFields -- (see MetaBrush.Render.Document.strokeRenderData).
. ( SuperRecord.RecApply ( MapFields UniqueField brushFields ) ( MapFields UniqueField brushFields )
( UseFieldsInBrush usedFields )
)
=> Super.Rec usedFields -> r
brushFunction usedParamsRecord =
let let
brushUniqParams :: Record UniqueField brushFields
brushUniqParams =
Rec.zipWith ( \ ( UniqueField uniq _ ) ( I val ) -> UniqueField uniq val )
defaultParamsRecord brushParams
updatedHeap :: Map Unique TypedTerm updatedHeap :: Map Unique TypedTerm
updatedHeap = bindRecordValues @brushFields @usedFields defaultParamsRecord usedParamsRecord evalHeap updatedHeap = bindRecordValues brushUniqParams evalHeap
in in
( `evalState` ( EvalState { evalHeap = updatedHeap, nextUnique } ) ) $ eval body ( `evalState` ( EvalState { evalHeap = updatedHeap, nextUnique } ) )
pure ( AdaptableFunction ( toBrushParameters, brushFunction ) ) $ eval body
pure $
WithParams
{ defaultParams = Rec.map (I . uniqueField) defaultParamsRecord
, withParams = brushFunction
}
eval ( Var var@( Located _ ( UniqueName _ varUniq ) ) ) = do eval ( Var var@( Located _ ( UniqueName _ varUniq ) ) ) = do
vars <- use ( field' @"evalHeap" ) vars <- use ( field' @"evalHeap" )
case Map.lookup varUniq vars of case Map.lookup varUniq vars of
@ -223,26 +238,17 @@ declareFun uniq@( UniqueName { nameUnique = funUnique } ) argPat rhs = do
pure uniq pure uniq
bindRecordValues bindRecordValues
:: forall brushFields usedFields defaultFields :: forall brushFields
. ( defaultFields ~ MapFields UniqueField brushFields . Record UniqueField brushFields
, SuperRecord.RecApply defaultFields defaultFields ( UseFieldsInBrush usedFields )
)
=> Super.Rec defaultFields
-> Super.Rec usedFields
-> Map Unique TypedTerm -> Map Unique TypedTerm
-> Map Unique TypedTerm -> Map Unique TypedTerm
bindRecordValues defaultValues usedValues heap = do bindRecordValues params heap =
SuperRecord.recApply @defaultFields @defaultFields @( UseFieldsInBrush usedFields ) foldRec bind_val params heap
( \ k ( UniqueField ( UniqueName _ uniq ) ( defaultVal :: a ) ) prevState ->
let where
val :: a bind_val :: UniqueField a -> Map Unique TypedTerm -> Map Unique TypedTerm
val = SuperRecord.lookupWithDefault k defaultVal usedValues bind_val ( UniqueField ( UniqueName _ uniq ) val ) =
updatedHeap :: Map Unique TypedTerm Map.insert uniq ( TypedTerm $ CExt ( Val val ) )
updatedHeap = Map.insert uniq ( TypedTerm $ CExt @Tc @a ( Val val ) ) prevState
in updatedHeap
)
defaultValues
heap
noSpan :: Span noSpan :: Span
noSpan = Span 0 0 0 0 noSpan = Span 0 0 0 0

View file

@ -0,0 +1,104 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralisedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
module MetaBrush.DSL.Interpolation
( Interpolatable(..)
, D(..), DRec
)
where
-- base
import Data.Kind
( Type )
import Data.Monoid
( Sum )
import Data.Proxy
( Proxy(..) )
import GHC.TypeLits
( Symbol )
-- acts
import Data.Act
( Act(..), Torsor(..) )
-- groups
import Data.Group
( Group(..) )
-- large-anon
import Data.Record.Anonymous
( Record, RecordDicts, I(..) )
import qualified Data.Record.Anonymous as Rec
( cpure, cmap, czipWith )
-- MetaBrush
import Math.Module
( Module(..) )
import Math.Vector2D
( Point2D, Vector2D )
--------------------------------------------------------------------------------
class ( Module Double ( Diff a ), Torsor ( Diff a ) a ) => Interpolatable a where
type Diff a = ( d :: Type ) | d -> a
instance ( a ~ Double ) => Interpolatable ( Point2D a ) where
type Diff ( Point2D a ) = Vector2D a
instance Interpolatable Double where
type Diff Double = Sum Double
--------------------------------------------------------------------------------
-- Linear/affine action for records.
type DRec :: [ ( Symbol, Type ) ] -> Type
type DRec = Record D
newtype D a = D { getDiff :: Diff a }
deriving newtype instance Semigroup (Diff a) => Semigroup (D a)
deriving newtype instance Monoid (Diff a) => Monoid (D a)
deriving newtype instance Group (Diff a) => Group (D a)
instance Interpolatable a => Act (D a) (I a) where
act (D d) (I a) = I (act d a)
instance Interpolatable a => Torsor (D a) (I a) where
I a --> I b = D (a --> b)
instance Interpolatable a => Module Double (D a) where
origin = D origin
D a ^+^ D b = D (a ^+^ b)
d *^ D a = D (d *^ a)
instance RecordDicts kvs Interpolatable
=> Semigroup (Record D kvs) where
(<>) = Rec.czipWith (Proxy @Interpolatable) (<>)
instance RecordDicts kvs Interpolatable
=> Monoid (Record D kvs) where
mempty = Rec.cpure (Proxy @Interpolatable) mempty
instance RecordDicts kvs Interpolatable
=> Group (Record D kvs) where
invert = Rec.cmap (Proxy @Interpolatable) invert
instance RecordDicts kvs Interpolatable
=> Act (Record D kvs) (Record I kvs) where
act = Rec.czipWith (Proxy @Interpolatable) act
instance RecordDicts kvs Interpolatable
=> Torsor (Record D kvs) (Record I kvs) where
(-->) = Rec.czipWith (Proxy @Interpolatable) (-->)
instance RecordDicts kvs Interpolatable
=> Module Double (Record D kvs) where
origin = Rec.cpure (Proxy @Interpolatable) origin
(^+^) = Rec.czipWith (Proxy @Interpolatable) (^+^)
d *^ r = Rec.cmap (Proxy @Interpolatable) (d *^) r
instance RecordDicts kvs Interpolatable
=> Interpolatable (Record I kvs) where
type Diff (Record I kvs) = Record D kvs

View file

@ -15,7 +15,7 @@
{-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns #-} {-# OPTIONS_GHC -fno-warn-incomplete-uni-patterns #-}
module MetaBrush.MetaParameter.Parse where module MetaBrush.DSL.Parse where
-- base -- base
import Control.Applicative import Control.Applicative
@ -67,14 +67,14 @@ import Math.Bezier.Spline
( SplineType(..), SSplineType(..), SplineTypeI(ssplineType) ( SplineType(..), SSplineType(..), SplineTypeI(ssplineType)
, Spline(..), Curves(..), Curve(..), NextPoint(..) , Spline(..), Curves(..), Curve(..), NextPoint(..)
) )
import MetaBrush.MetaParameter.AST import MetaBrush.DSL.AST
( Span(..), Located(..) ( Span(..), Located(..)
, Expr, EPat , Expr, EPat
, Term(..), Pat(..), Decl(..) , Term(..), Pat(..), Decl(..)
, X_With(..) , X_With(..)
, toTreeTerm , toTreeTerm
) )
import MetaBrush.MetaParameter.PrimOp import MetaBrush.DSL.PrimOp
( Orientation(..), kappa ( Orientation(..), kappa
, rotate_around_by, rotate_by , rotate_around_by, rotate_by
, scale_around_by, scale_by , scale_around_by, scale_by

View file

@ -1,7 +1,7 @@
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingStrategies #-}
module MetaBrush.MetaParameter.PrimOp where module MetaBrush.DSL.PrimOp where
-- MetaBrush -- MetaBrush
import Math.Bezier.Spline import Math.Bezier.Spline

View file

@ -9,7 +9,7 @@
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilies #-}
module MetaBrush.MetaParameter.Rename module MetaBrush.DSL.Rename
( rename, MonadRn, RnM ( rename, MonadRn, RnM
, RnMessage, RnError , RnMessage, RnError
, RnState, emptyRnState , RnState, emptyRnState
@ -60,12 +60,12 @@ import Control.Monad.Trans.RWS.CPS
-- MetaBrush -- MetaBrush
import Math.Bezier.Spline import Math.Bezier.Spline
( KnownSplineType(bitraverseSpline), bitraverseCurve ) ( KnownSplineType(bitraverseSpline), bitraverseCurve )
import MetaBrush.MetaParameter.AST import MetaBrush.DSL.AST
( Located(..) ( Located(..)
, Pass(P,Rn), Name, UniqueName(..), X_With(..) , Pass(P,Rn), Name, UniqueName(..), X_With(..)
, Term(..), Decl(..), Pat(..) , Term(..), Decl(..), Pat(..)
) )
import MetaBrush.MetaParameter.Parse import MetaBrush.DSL.Parse
( ) -- AST type family instances for parsing pass ( ) -- AST type family instances for parsing pass
import MetaBrush.Unique import MetaBrush.Unique
( UniqueSupply, MonadUnique(freshUnique) ( UniqueSupply, MonadUnique(freshUnique)

View file

@ -13,48 +13,38 @@
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilyDependencies #-} {-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-} {-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
module MetaBrush.MetaParameter.TypeCheck module MetaBrush.DSL.TypeCheck
( typeCheck, MonadTc, TcM ( typeCheck, MonadTc, TcM
, TcMessage, TcError , TcMessage, TcError
, TcState, emptyTcState , TcState, emptyTcState
) )
where where
import Data.Kind
( Type )
-- base -- base
import Control.Arrow
( first, second )
import Data.Either import Data.Either
( partitionEithers ) ( partitionEithers )
import Data.Functor.Compose import Data.Kind
( Compose(..) ) ( Type )
import Data.List
( sortOn )
import Data.Ord
( Down(..) )
import Data.Proxy
( Proxy )
import Data.Type.Equality import Data.Type.Equality
( (:~:)(Refl) ) ( (:~:)(Refl) )
import GHC.Exts import GHC.Exts
( Proxy#, proxy# ) ( Any, Proxy#, proxy# )
import GHC.Generics import GHC.Generics
( Generic ) ( Generic )
import GHC.TypeLits
( someSymbolVal, SomeSymbol(..) )
import GHC.TypeNats
( KnownNat )
import Unsafe.Coerce import Unsafe.Coerce
( unsafeCoerce ) ( unsafeCoerce )
-- containers -- containers
import Data.Map.Strict import Data.Map.Strict
( Map ) ( Map )
import qualified Data.Map.Strict as Map
( fromList )
import Data.Sequence import Data.Sequence
( Seq(..) ) ( Seq(..) )
@ -66,6 +56,13 @@ import Data.DList
import Data.Generics.Product.Fields import Data.Generics.Product.Fields
( field' ) ( field' )
-- large-anon
import Data.Record.Anonymous
( Record
)
import Data.Record.Anonymous.Internal
( Record(MkR) )
-- lens -- lens
import Control.Lens import Control.Lens
( assign, at, use ) ( assign, at, use )
@ -78,16 +75,6 @@ import Control.Monad.State
import Control.Monad.Writer import Control.Monad.Writer
( MonadWriter(..) ) ( MonadWriter(..) )
-- superrecord
import qualified SuperRecord as Super
( Rec )
import qualified SuperRecord
( (:=)(..), FldProxy(..), RecSize, RecApply
, RecTy, RemoveAccessTo, RecVecIdxPos
, TraversalCHelper
, unsafeRNil, unsafeRCons
)
-- text -- text
import Data.Text import Data.Text
( Text ) ( Text )
@ -109,18 +96,21 @@ import Math.Bezier.Spline
) )
import Math.Vector2D import Math.Vector2D
( Point2D(..) ) ( Point2D(..) )
import MetaBrush.MetaParameter.AST import MetaBrush.DSL.AST
( Span(..), Located(..) ( Span(..), Located(..)
, Pass(Rn,Tc) , Pass(Rn,Tc)
, Pat(..), Decl(..) , Pat(..), Decl(..)
, X_With(..), MapFields , X_With(..)
, UniqueTerm, UniqueField(..), IsUniqueTerm, IsUniqueTerm2 , UniqueTerm(..)
, SType(..), STypeI(sTypeI), SomeSType(..) , Term(..), TypedTerm(..)
, STypes(..), STypesI(..)
, Term(..), TypedTerm(..), eqTy
, termSpan , termSpan
) )
import MetaBrush.MetaParameter.Rename import MetaBrush.DSL.Types
( SType(..), STypeI(sTypeI), SomeSType(..)
, STypesI(..)
, eqTy, proveSomeSTypes
)
import MetaBrush.DSL.Rename
( Env(..), UniqueName(..) ) ( Env(..), UniqueName(..) )
import MetaBrush.Unique import MetaBrush.Unique
( UniqueSupply, MonadUnique, Unique ) ( UniqueSupply, MonadUnique, Unique )
@ -174,11 +164,7 @@ typeCheck ( With locs ( Rn_With decls ) conds body ) = do
decls' <- typeCheckDecls decls decls' <- typeCheckDecls decls
conds' <- traverse ( typeCheckAt @Bool "Expected Boolean condition, but expression has the wrong type." ) conds conds' <- traverse ( typeCheckAt @Bool "Expected Boolean condition, but expression has the wrong type." ) conds
TypedTerm body' <- typeCheck body TypedTerm body' <- typeCheck body
withDeclsRecord decls' \ ( decls'Record :: Super.Rec ( MapFields UniqueTerm kvs ) ) -> do withDeclsRecord decls' \ ( decls'Record :: Record UniqueTerm kvs ) ->
case unsafeCoerce Refl :: SuperRecord.RecSize ( MapFields UniqueTerm kvs ) :~: SuperRecord.RecSize kvs of
Refl ->
case treeArgsDict @kvs @kvs of
RecTreeArgsDict ->
TypedTerm $ With locs ( Tc_With decls'Record ) conds' body' TypedTerm $ With locs ( Tc_With decls'Record ) conds' body'
typeCheck ( Lit loc a ) = pure ( TypedTerm $ Lit loc a ) typeCheck ( Lit loc a ) = pure ( TypedTerm $ Lit loc a )
typeCheck ( Op locs nm op ) = pure ( TypedTerm $ Op locs nm op ) typeCheck ( Op locs nm op ) = pure ( TypedTerm $ Op locs nm op )
@ -303,76 +289,26 @@ withDeclsRecord
:: forall r m :: forall r m
. ( MonadTc m ) . ( MonadTc m )
=> [ Decl Tc ] => [ Decl Tc ]
-> ( forall kvs. STypesI kvs => Super.Rec ( MapFields UniqueTerm kvs ) -> r ) -> ( forall kvs. STypesI kvs => Record UniqueTerm kvs -> r )
-> m r -> m r
withDeclsRecord decls f = do withDeclsRecord decls f = do
TypedTermsRecord record <- go ( TypedTermsRecord $ SuperRecord.unsafeRNil lg ) <$> ( revSortDecls decls ) -- This list cannot have duplicate names, as these would have been caught by the renamer.
pure ( f record ) names <- traverse getDeclName decls
where let
lg :: Int mkSomeSType :: forall a. UniqueTerm a -> SomeSType
lg = length decls mkSomeSType ( UniqueTerm {} ) = SomeSType @a proxy#
-- This list cannot have duplicate names, proveSomeSTypes (map (second mkSomeSType) names) \ ( _ :: Proxy# kvs ) -> do
-- as these would have been caught by the renamer. let
-- Sort in reverse order as we must add elements in decreasing label order. declsRecord :: Record UniqueTerm kvs
revSortDecls :: [ Decl Tc ] -> m [ ( Text, ( UniqueName, TypedTerm ) ) ] declsRecord = MkR (Map.fromList . map (first Text.unpack) $ names)
revSortDecls = fmap ( sortOn ( Down . fst ) ) . traverse getDeclName return $ f declsRecord
getDeclName :: Decl Tc -> m ( Text, ( UniqueName, TypedTerm ) )
getDeclName ( ValDecl pat ( Located eqLoc _ ) term ) = case pat of getDeclName :: MonadTc m => Decl Tc -> m ( Text, UniqueTerm Any )
PName ( Located _ uniq@( UniqueName nm _ ) ) -> pure ( nm, ( uniq, TypedTerm term ) ) getDeclName ( ValDecl pat ( Located eqLoc _ ) term ) = case pat of
AsPat _ ( Located _ uniq@( UniqueName nm _ ) ) _ -> pure ( nm, ( uniq, TypedTerm term ) ) PName ( Located _ uniq@( UniqueName nm _ ) ) -> pure ( nm, unsafeCoerce $ UniqueTerm uniq term )
AsPat _ ( Located _ uniq@( UniqueName nm _ ) ) _ -> pure ( nm, unsafeCoerce $ UniqueTerm uniq term )
_ -> tcError $ NoPatternName eqLoc _ -> tcError $ NoPatternName eqLoc
getDeclName ( FunDecl funName _ _ _ ) = tcError $ UnexpectedFunDecl funName getDeclName ( FunDecl funName _ _ _ ) = tcError $ UnexpectedFunDecl funName
go :: TypedTermsRecord -> [ ( Text, ( UniqueName, TypedTerm ) ) ] -> TypedTermsRecord
go record [] = record
go ( TypedTermsRecord ( record :: Super.Rec ( MapFields UniqueTerm kvs ) ) )
( ( nm, ( uniq, TypedTerm ( t :: Term Tc a ) ) ) : ps )
= case someSymbolVal ( Text.unpack nm ) of
SomeSymbol ( _ :: Proxy nm ) ->
go
( TypedTermsRecord @( ( nm SuperRecord.:= a ) ': kvs )
$ SuperRecord.unsafeRCons @nm @( UniqueTerm a ) @( MapFields UniqueTerm kvs )
( SuperRecord.FldProxy @nm SuperRecord.:= Compose ( UniqueField uniq t ) )
record
)
ps
data TypedTermsRecord where
TypedTermsRecord
:: ( STypesI kvs, ts ~ MapFields UniqueTerm kvs, KnownNat ( SuperRecord.RecSize ts ) )
=> Super.Rec ts -> TypedTermsRecord
data RecTreeArgsDict rts lts where
RecTreeArgsDict
:: forall rts lts trts tlts frts flts
. ( trts ~ MapFields UniqueTerm rts, tlts ~ MapFields UniqueTerm lts
, frts ~ MapFields UniqueField rts, flts ~ MapFields UniqueField lts
, SuperRecord.RecApply trts tlts IsUniqueTerm
, SuperRecord.TraversalCHelper flts trts frts IsUniqueTerm2
)
=> RecTreeArgsDict rts lts
treeArgsDict
:: forall rts lts trts tlts frts flts
. ( trts ~ MapFields UniqueTerm rts, tlts ~ MapFields UniqueTerm lts
, frts ~ MapFields UniqueField rts, flts ~ MapFields UniqueField lts
, STypesI lts
, KnownNat ( SuperRecord.RecSize rts )
)
=> RecTreeArgsDict rts lts
treeArgsDict = case sTypesI @lts of
STyNil
| Refl <- ( unsafeCoerce Refl :: SuperRecord.RecSize frts :~: SuperRecord.RecSize rts )
-> RecTreeArgsDict
sTyCons@STyCons
| ( _ :: STypes ( ( l SuperRecord.:= v ) ': lvs ) ) <- sTyCons
, Refl <- ( unsafeCoerce Refl :: MapFields UniqueTerm lvs :~: SuperRecord.RemoveAccessTo l ( MapFields UniqueTerm lvs ) )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecTy l trts :~: Just ( UniqueTerm v ) )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecVecIdxPos l trts :~: SuperRecord.RecSize lvs )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecSize trts :~: SuperRecord.RecSize rts )
, Refl <- ( unsafeCoerce Refl :: SuperRecord.RecSize lvs :~: SuperRecord.RecSize ( MapFields UniqueField lvs ) )
-> case treeArgsDict @rts @lvs of
RecTreeArgsDict -> RecTreeArgsDict
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Type-checker-specific data and instances. -- Type-checker-specific data and instances.

View file

@ -0,0 +1,225 @@
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module MetaBrush.DSL.Types
( SType(..), STypes(..)
, STypeI(..), STypesI(..)
, SomeSType(..)
, eqTy, eqTys
, someSTypes, proveSomeSTypes
) where
-- base
import Data.Kind
( Constraint, Type )
import Data.List
( intercalate )
import Data.Proxy
( Proxy(..) )
import Data.Type.Equality
( (:~:)(Refl) )
import GHC.Exts
( Proxy#, proxy# )
import GHC.TypeLits
( Symbol, KnownSymbol, SomeSymbol(..)
, symbolVal', sameSymbol, someSymbolVal )
-- text
import Data.Text
( Text )
import qualified Data.Text as Text
( pack, unpack )
-- MetaBrush
import Math.Vector2D
( Point2D(..), Segment(..) )
import qualified Math.Bezier.Cubic as Cubic
( Bezier(..) )
import qualified Math.Bezier.Quadratic as Quadratic
( Bezier(..) )
import Math.Bezier.Spline
( SplinePts
, SSplineType(..), SplineTypeI(ssplineType)
, KnownSplineType
)
import MetaBrush.Records
( WithParams )
--------------------------------------------------------------------------------
-- Types.
type SType :: Type -> Type
data SType ty where
SFunTy :: ( STypeI a, STypeI b ) => SType ( a -> b )
STyBool :: SType Bool
STyDouble :: SType Double
STyPoint :: STypeI a => SType ( Point2D a )
STyLine :: STypeI a => SType ( Segment a )
STyBez2 :: STypeI a => SType ( Quadratic.Bezier a )
STyBez3 :: STypeI a => SType ( Cubic.Bezier a )
STySpline :: KnownSplineType clo => SType ( SplinePts clo )
STyWithFn :: ( STypesI kvs, STypeI a ) => SType ( WithParams kvs a )
-- reminder: update eqSTy when adding new constructors
deriving stock instance Show ( SType ty )
class STypeI ty where
sTypeI :: SType ty
instance ( STypeI a, STypeI b ) => STypeI ( a -> b ) where
sTypeI = SFunTy
instance STypeI Bool where
sTypeI = STyBool
instance STypeI Double where
sTypeI = STyDouble
instance STypeI a => STypeI ( Point2D a ) where
sTypeI = STyPoint
instance STypeI a => STypeI ( Segment a ) where
sTypeI = STyLine
instance STypeI a => STypeI ( Quadratic.Bezier a ) where
sTypeI = STyBez2
instance STypeI a => STypeI ( Cubic.Bezier a ) where
sTypeI = STyBez3
instance KnownSplineType clo => STypeI ( SplinePts clo ) where
sTypeI = STySpline
instance ( STypesI kvs, STypeI a ) => STypeI ( WithParams kvs a ) where
sTypeI = STyWithFn
type STypes :: [ (Symbol, Type) ] -> Type
data STypes kvs where
STyNil :: STypes '[]
STyCons :: ( kv ~ '( k, v ), KnownSymbol k, STypeI v, STypesI kvs ) => STypes ( kv ': kvs )
instance Show ( STypes kvs ) where
show sTypes = "'[" <> intercalate "," ( showSTypes sTypes ) <> "]"
showSTypes :: STypes kvs -> [ String ]
showSTypes STyNil = []
showSTypes sTyCons@STyCons
| ( _ :: STypes ( '( k, v ) ': tail_kvs ) ) <- sTyCons
= ( symbolVal' ( proxy# :: Proxy# k ) <> " := " <> show ( sTypeI @v ) ) : showSTypes ( sTypesI @tail_kvs )
type STypesI :: [ (Symbol, Type) ] -> Constraint
class STypesI kvs where
sTypesI :: STypes kvs
instance STypesI '[] where
sTypesI = STyNil
-- Warning: this instance is somewhat overly general as it doesn't check for lack of duplicates
instance ( kv ~ '( k, v ), KnownSymbol k, STypeI v, STypesI kvs ) => STypesI ( kv ': kvs ) where
sTypesI = STyCons
eqSTy :: SType a -> SType b -> Maybe ( a :~: b )
eqSTy sTy_a@SFunTy sTy_b@SFunTy
| ( _ :: SType ( a1 -> b1 ) ) <- sTy_a
, ( _ :: SType ( a2 -> b2 ) ) <- sTy_b
, Just Refl <- eqTy @a1 @a2
, Just Refl <- eqTy @b1 @b2
= Just Refl
eqSTy STyBool STyBool = Just Refl
eqSTy STyDouble STyDouble = Just Refl
eqSTy sTy_a@STyPoint sTy_b@STyPoint
| ( _ :: SType ( Point2D l ) ) <- sTy_a
, ( _ :: SType ( Point2D r ) ) <- sTy_b
, Just Refl <- eqTy @l @r
= Just Refl
eqSTy sTy_a@STyLine sTy_b@STyLine
| ( _ :: SType ( Segment l ) ) <- sTy_a
, ( _ :: SType ( Segment r ) ) <- sTy_b
, Just Refl <- eqTy @l @r
= Just Refl
eqSTy sTy_a@STyBez2 sTy_b@STyBez2
| ( _ :: SType ( Quadratic.Bezier l ) ) <- sTy_a
, ( _ :: SType ( Quadratic.Bezier r ) ) <- sTy_b
, Just Refl <- eqTy @l @r
= Just Refl
eqSTy sTy_a@STyBez3 sTy_b@STyBez3
| ( _ :: SType ( Cubic.Bezier l ) ) <- sTy_a
, ( _ :: SType ( Cubic.Bezier r ) ) <- sTy_b
, Just Refl <- eqTy @l @r
= Just Refl
eqSTy sTy_a@STySpline sTy_b@STySpline
| ( _ :: SType ( SplinePts clo1 ) ) <- sTy_a
, ( _ :: SType ( SplinePts clo2 ) ) <- sTy_b
= case ( ssplineType @clo1, ssplineType @clo2 ) of
( SOpen , SOpen ) -> Just Refl
( SClosed, SClosed ) -> Just Refl
_ -> Nothing
eqSTy sTy_a@STyWithFn sTy_b@STyWithFn
| ( _ :: SType ( WithParams kvs a ) ) <- sTy_a
, ( _ :: SType ( WithParams lvs b ) ) <- sTy_b
, Just Refl <- eqTys @kvs @lvs
, Just Refl <- eqTy @a @b
= Just Refl
eqSTy _ _ = Nothing
eqTy :: forall a b. ( STypeI a, STypeI b ) => Maybe ( a :~: b )
eqTy = eqSTy ( sTypeI @a ) ( sTypeI @b )
eqSTys :: STypes as -> STypes bs -> Maybe ( as :~: bs )
eqSTys STyNil STyNil = Just Refl
eqSTys sTyCons1@STyCons sTyCons2@STyCons
| ( _ :: STypes ( '( l1, v1 ) ': as' ) ) <- sTyCons1
, ( _ :: STypes ( '( l2, v2 ) ': bs' ) ) <- sTyCons2
, Just Refl <- sameSymbol ( Proxy :: Proxy l1 ) ( Proxy :: Proxy l2 )
, Just Refl <- eqTy @v1 @v2
, Just Refl <- eqTys @as' @bs'
= Just Refl
eqSTys _ _ = Nothing
eqTys :: forall as bs. ( STypesI as, STypesI bs ) => Maybe ( as :~: bs )
eqTys = eqSTys ( sTypesI @as ) ( sTypesI @bs )
data SomeSType where
SomeSType :: STypeI a => Proxy# a -> SomeSType
instance Show SomeSType where
show ( SomeSType ( _ :: Proxy# a ) ) = show ( sTypeI @a )
instance Eq SomeSType where
( SomeSType ( _ :: Proxy# a ) ) == ( SomeSType ( _ :: Proxy# b ) ) =
case eqTy @a @b of
Just _ -> True
_ -> False
data SomeSTypes where
SomeSTypes :: STypesI kvs => Proxy# kvs -> SomeSTypes
someSTypes :: forall kvs. STypesI kvs => [ ( Text, SomeSType ) ]
someSTypes = go ( sTypesI @kvs )
where
go :: forall lvs. STypes lvs -> [ ( Text, SomeSType ) ]
go STyNil = []
go sTyCons@STyCons
| ( _ :: STypes ( '( l, v ) ': lvs' ) ) <- sTyCons
, let
l :: Text
l = Text.pack $ symbolVal' ( proxy# :: Proxy# l )
= ( l, SomeSType ( proxy# :: Proxy# v ) )
: go ( sTypesI @lvs' )
proveSomeSTypes :: [ ( Text, SomeSType ) ] -> ( forall kvs. STypesI kvs => Proxy# kvs -> r ) -> r
proveSomeSTypes rs f = case go rs of { SomeSTypes ( _ :: Proxy# kvs ) -> f @kvs proxy# }
where
go :: [ ( Text, SomeSType ) ] -> SomeSTypes
go [] = SomeSTypes @'[] proxy#
go ( ( s, SomeSType ( _ :: Proxy# v ) ) :rest )
= case go rest of
SomeSTypes ( _ :: Proxy# kvs )
| SomeSymbol ( _ :: Proxy k ) <- someSymbolVal ( Text.unpack s )
-> SomeSTypes @( '( k, v ) ': kvs ) proxy#

View file

@ -74,6 +74,10 @@ import Data.Generics.Product.Fields
import Data.Group import Data.Group
( Group(..) ) ( Group(..) )
-- large-anon
import Data.Record.Anonymous
( RecordDicts )
-- lens -- lens
import Control.Lens import Control.Lens
( Lens' ( Lens'
@ -84,10 +88,6 @@ import Control.Lens
import Control.Concurrent.STM import Control.Concurrent.STM
( STM ) ( STM )
-- superrecord
import qualified SuperRecord as Super
( Rec )
-- text -- text
import Data.Text import Data.Text
( Text ) ( Text )
@ -110,13 +110,15 @@ import Math.Module
import Math.Vector2D import Math.Vector2D
( Point2D(..), Vector2D(..) ) ( Point2D(..), Vector2D(..) )
import MetaBrush.Brush import MetaBrush.Brush
( BrushAdaptedTo ) ( Brush )
import {-# SOURCE #-} MetaBrush.Document.Serialise import {-# SOURCE #-} MetaBrush.Document.Serialise
( Serialisable(..) ) ( Serialisable(..) )
import MetaBrush.MetaParameter.AST import MetaBrush.DSL.Types
( STypesI(..) ) ( STypesI(..) )
import MetaBrush.MetaParameter.Interpolation import MetaBrush.DSL.Interpolation
( Interpolatable(..) ) -- + orphan instances ( Interpolatable(..) )
import MetaBrush.Records
( Rec )
import MetaBrush.UI.Viewport import MetaBrush.UI.Viewport
( Ruler(..) ) ( Ruler(..) )
import MetaBrush.Unique import MetaBrush.Unique
@ -194,16 +196,17 @@ type StrokeSpline clo brushParams =
data Stroke where data Stroke where
Stroke Stroke
:: ( KnownSplineType clo :: ( KnownSplineType clo
, pointParams ~ Super.Rec pointFields, STypesI pointFields , pointParams ~ Rec pointFields
, STypesI pointFields, STypesI brushFields
, Show pointParams, NFData pointParams , Show pointParams, NFData pointParams
, Interpolatable pointParams , RecordDicts pointFields Interpolatable
, Serialisable pointParams , Serialisable pointParams
) )
=> =>
{ strokeName :: !Text { strokeName :: !Text
, strokeVisible :: !Bool , strokeVisible :: !Bool
, strokeUnique :: Unique , strokeUnique :: Unique
, strokeBrush :: !( Maybe ( BrushAdaptedTo pointFields ) ) , strokeBrush :: !( Maybe ( Brush brushFields ) )
, strokeSpline :: !( StrokeSpline clo pointParams ) , strokeSpline :: !( StrokeSpline clo pointParams )
} }
-> Stroke -> Stroke
@ -222,8 +225,8 @@ _strokeSpline
=> ( forall clo pointParams pointFields => ( forall clo pointParams pointFields
. ( KnownSplineType clo . ( KnownSplineType clo
, Show pointParams, NFData pointParams , Show pointParams, NFData pointParams
, pointParams ~ Super.Rec pointFields, STypesI pointFields , RecordDicts pointFields Interpolatable
, Interpolatable pointParams , pointParams ~ Rec pointFields, STypesI pointFields
, Serialisable pointParams , Serialisable pointParams
) )
=> StrokeSpline clo pointParams => StrokeSpline clo pointParams
@ -237,8 +240,8 @@ overStrokeSpline
:: ( forall clo pointParams pointFields :: ( forall clo pointParams pointFields
. ( KnownSplineType clo . ( KnownSplineType clo
, Show pointParams, NFData pointParams , Show pointParams, NFData pointParams
, pointParams ~ Super.Rec pointFields, STypesI pointFields , RecordDicts pointFields Interpolatable
, Interpolatable pointParams , pointParams ~ Rec pointFields, STypesI pointFields
, Serialisable pointParams , Serialisable pointParams
) )
=> StrokeSpline clo pointParams => StrokeSpline clo pointParams

View file

@ -1,6 +1,7 @@
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-} {-# LANGUAGE GADTs #-}
{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
@ -9,6 +10,8 @@
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -fplugin=Data.Record.Anonymous.Plugin #-}
module MetaBrush.Document.Draw module MetaBrush.Document.Draw
( DrawAnchor(..), anchorsAreComplementary ( DrawAnchor(..), anchorsAreComplementary
, getOrCreateDrawAnchor, addToAnchor , getOrCreateDrawAnchor, addToAnchor
@ -40,6 +43,12 @@ import Control.DeepSeq
import Data.Generics.Product.Fields import Data.Generics.Product.Fields
( field, field' ) ( field, field' )
-- large-anon
import Data.Record.Anonymous
( RecordDicts )
import qualified Data.Record.Anonymous as Rec
( empty )
-- lens -- lens
import Control.Lens import Control.Lens
( set, over, mapped ) ( set, over, mapped )
@ -48,12 +57,6 @@ import Control.Lens
import Control.Concurrent.STM import Control.Concurrent.STM
( STM ) ( STM )
-- superrecord
import qualified SuperRecord as Super
( Rec )
import qualified SuperRecord
( rnil )
-- text -- text
import Data.Text import Data.Text
( Text ) ( Text )
@ -79,7 +82,7 @@ import Math.Vector2D
import MetaBrush.Assert import MetaBrush.Assert
( assert ) ( assert )
import MetaBrush.Brush import MetaBrush.Brush
( BrushAdaptedTo ) ( Brush(..) )
import MetaBrush.Document import MetaBrush.Document
( Document(..), DocumentContent(..) ( Document(..), DocumentContent(..)
, Stroke(..), StrokeHierarchy(..), StrokeSpline , Stroke(..), StrokeHierarchy(..), StrokeSpline
@ -89,10 +92,12 @@ import MetaBrush.Document
) )
import MetaBrush.Document.Serialise import MetaBrush.Document.Serialise
( Serialisable ) ( Serialisable )
import MetaBrush.MetaParameter.AST import MetaBrush.DSL.Types
( STypesI(..) ) ( STypesI(..) )
import MetaBrush.MetaParameter.Interpolation import MetaBrush.DSL.Interpolation
( Interpolatable ) ( Interpolatable )
import MetaBrush.Records
( Rec )
import MetaBrush.Unique import MetaBrush.Unique
( Unique, UniqueSupply, freshUnique, uniqueText ) ( Unique, UniqueSupply, freshUnique, uniqueText )
@ -132,9 +137,9 @@ getOrCreateDrawAnchor uniqueSupply c doc@( Document { zoomFactor } ) =
( newDoc, Nothing ) -> do ( newDoc, Nothing ) -> do
uniq <- runReaderT freshUnique uniqueSupply uniq <- runReaderT freshUnique uniqueSupply
let let
newSpline :: StrokeSpline Open ( Super.Rec '[] ) newSpline :: StrokeSpline Open ( Rec '[] )
newSpline = newSpline =
Spline { splineStart = PointData c Normal ( SuperRecord.rnil ) Spline { splineStart = PointData c Normal Rec.empty
, splineCurves = OpenCurves Empty , splineCurves = OpenCurves Empty
} }
newStroke :: Stroke newStroke :: Stroke
@ -144,7 +149,7 @@ getOrCreateDrawAnchor uniqueSupply c doc@( Document { zoomFactor } ) =
, strokeVisible = True , strokeVisible = True
, strokeUnique = uniq , strokeUnique = uniq
, strokeSpline = newSpline , strokeSpline = newSpline
, strokeBrush = Nothing , strokeBrush = Nothing :: Maybe ( Brush '[] )
} }
newDoc' :: Document newDoc' :: Document
newDoc' newDoc'
@ -222,8 +227,7 @@ addToAnchor anchor newSpline = over ( field' @"documentContent" . field' @"strok
updateStroke :: Stroke -> Stroke updateStroke :: Stroke -> Stroke
updateStroke stroke@( Stroke { strokeUnique } ) updateStroke stroke@( Stroke { strokeUnique } )
| strokeUnique == anchorStrokeUnique anchor | strokeUnique == anchorStrokeUnique anchor
= , let
let
updateSpline updateSpline
:: forall clo brushData :: forall clo brushData
. SplineTypeI clo . SplineTypeI clo
@ -244,8 +248,7 @@ addToAnchor anchor newSpline = over ( field' @"documentContent" . field' @"strok
| otherwise | otherwise
= assert ( "addToAnchor: trying to add to closed spline " <> show strokeUnique ) = assert ( "addToAnchor: trying to add to closed spline " <> show strokeUnique )
prevSpline -- should never add to a closed spline prevSpline -- should never add to a closed spline
in = overStrokeSpline updateSpline stroke
overStrokeSpline updateSpline stroke
| otherwise | otherwise
= stroke = stroke
@ -253,13 +256,14 @@ withAnchorBrushData
:: forall r :: forall r
. DrawAnchor . DrawAnchor
-> Document -> Document
-> ( forall pointParams pointFields -> ( forall pointParams pointFields brushFields
. ( pointParams ~ Super.Rec pointFields, STypesI pointFields . ( pointParams ~ Rec pointFields
, STypesI pointFields, STypesI brushFields
, Show pointParams, NFData pointParams , Show pointParams, NFData pointParams
, Interpolatable pointParams
, Serialisable pointParams , Serialisable pointParams
, RecordDicts pointFields Interpolatable
) )
=> Maybe ( BrushAdaptedTo pointFields ) => Maybe (Brush brushFields)
-> pointParams -> pointParams
-> r -> r
) )
@ -284,4 +288,4 @@ withAnchorBrushData anchor ( Document { documentContent = Content { strokes } }
AnchorAtStart {} -> f strokeBrush ( brushParams ( splineStart strokeSpline ) ) AnchorAtStart {} -> f strokeBrush ( brushParams ( splineStart strokeSpline ) )
AnchorAtEnd {} -> f strokeBrush ( brushParams ( splineEnd strokeSpline ) ) AnchorAtEnd {} -> f strokeBrush ( brushParams ( splineEnd strokeSpline ) )
splineAnchor _ splineAnchor _
= f Nothing SuperRecord.rnil = f (Nothing :: Maybe (Brush '[])) Rec.empty

View file

@ -126,7 +126,7 @@ import MetaBrush.Document
) )
import {-# SOURCE #-} MetaBrush.Document.Update import {-# SOURCE #-} MetaBrush.Document.Update
( DocChange(..) ) ( DocChange(..) )
import MetaBrush.MetaParameter.Interpolation import MetaBrush.DSL.Interpolation
( Interpolatable(Diff) ) ( Interpolatable(Diff) )
import MetaBrush.Unique import MetaBrush.Unique
( Unique ) ( Unique )

View file

@ -1,6 +1,7 @@
{-# LANGUAGE BlockArguments #-} {-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DataKinds #-} {-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-} {-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
@ -14,8 +15,7 @@
{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableInstances #-}
module MetaBrush.Document.Serialise module MetaBrush.Document.Serialise
( Workaround(..), workaround ( Serialisable(..)
, Serialisable(..)
, documentToJSON, documentFromJSON , documentToJSON, documentFromJSON
, saveDocument, loadDocument , saveDocument, loadDocument
) )
@ -36,6 +36,8 @@ import Data.Functor.Contravariant
( contramap ) ( contramap )
import Data.Functor.Identity import Data.Functor.Identity
( Identity(..) ) ( Identity(..) )
import Data.Proxy
( Proxy(..) )
import Data.STRef import Data.STRef
( newSTRef ) ( newSTRef )
import Data.Type.Equality import Data.Type.Equality
@ -45,9 +47,7 @@ import Data.Version
import GHC.Exts import GHC.Exts
( Proxy#, proxy# ) ( Proxy#, proxy# )
import GHC.TypeLits import GHC.TypeLits
( symbolVal', KnownSymbol ) ( KnownSymbol, symbolVal )
import GHC.TypeNats
( KnownNat )
import Unsafe.Coerce import Unsafe.Coerce
( unsafeCoerce ) -- Tony Morris special ( unsafeCoerce ) -- Tony Morris special
@ -87,6 +87,14 @@ import System.FilePath
import Data.Generics.Product.Typed import Data.Generics.Product.Typed
( HasType(typed) ) ( HasType(typed) )
-- large-anon
import Data.Record.Anonymous
( Record, RecordDicts(..)
, K(..), I(..), unI
)
import qualified Data.Record.Anonymous as Rec
( collapse )
-- lens -- lens
import Control.Lens import Control.Lens
( view ) ( view )
@ -103,17 +111,6 @@ import qualified Data.Scientific as Scientific
import qualified Control.Concurrent.STM as STM import qualified Control.Concurrent.STM as STM
( atomically ) ( atomically )
-- superrecord
import qualified SuperRecord as Super
( Rec )
import qualified SuperRecord
( FldProxy(..)
, RecSize, RecApply(..), UnsafeRecBuild(..)
, reflectRec
)
import SuperRecord
( ConstC )
-- text -- text
import Data.Text import Data.Text
( Text ) ( Text )
@ -177,22 +174,25 @@ import Math.Vector2D
( Point2D(..), Vector2D(..), Segment ) ( Point2D(..), Vector2D(..), Segment )
import MetaBrush.Brush import MetaBrush.Brush
( Brush(..), SomeBrush(..) ( Brush(..), SomeBrush(..)
, BrushAdaptedTo(..), adaptBrush , SomeFieldSType(..), SomeBrushFields(..)
, SomeBrushFields(..), SomeFieldSType(..), reflectBrushFieldsNoDups , reflectBrushFieldsNoDups
) )
import MetaBrush.Document import MetaBrush.Document
( Document(..), DocumentContent(..), Guide(..) ( Document(..), DocumentContent(..), Guide(..)
, Stroke(..), StrokeHierarchy(..), StrokeSpline , Stroke(..), StrokeHierarchy(..), StrokeSpline
, PointData(..), FocusState(..) , PointData(..), FocusState(..)
) )
import MetaBrush.MetaParameter.AST import MetaBrush.DSL.Types
( SType(..), STypeI(..) ( SType(..), STypeI(..)
, SomeSType(..), someSTypes , SomeSType(..), someSTypes
, AdaptableFunction(..)
, eqTy , eqTy
) )
import MetaBrush.MetaParameter.Driver import MetaBrush.DSL.Driver
( SomeBrushFunction(..), interpretBrush ) ( SomeBrushFunction(..), interpretBrush )
import MetaBrush.Records
( Rec, WithParams
, cpureM, cmapWithKey
)
import MetaBrush.Unique import MetaBrush.Unique
( Unique, UniqueSupply, freshUnique ) ( Unique, UniqueSupply, freshUnique )
import qualified Paths_MetaBrush as Cabal import qualified Paths_MetaBrush as Cabal
@ -200,11 +200,6 @@ import qualified Paths_MetaBrush as Cabal
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- | Dummy data-type that helps workaround a GHC bug with hs-boot files.
data Workaround = Workaround
workaround :: Workaround -> Workaround
workaround Workaround = Workaround
-- | Serialise a document to JSON (in the form of a lazy bytestring). -- | Serialise a document to JSON (in the form of a lazy bytestring).
documentToJSON :: Document -> Lazy.ByteString documentToJSON :: Document -> Lazy.ByteString
documentToJSON documentToJSON
@ -276,31 +271,22 @@ instance Serialisable a => Serialisable ( Vector2D a ) where
. JSON.Encoder.atKey' "y" encoder y . JSON.Encoder.atKey' "y" encoder y
decoder = Vector2D <$> JSON.Decoder.atKey "x" decoder <*> JSON.Decoder.atKey "y" decoder decoder = Vector2D <$> JSON.Decoder.atKey "x" decoder <*> JSON.Decoder.atKey "y" decoder
instance ( SuperRecord.RecApply flds flds ( ConstC Serialisable ) instance Serialisable a => Serialisable (I a) where
, SuperRecord.UnsafeRecBuild flds flds ( ConstC Serialisable ) encoder = contramap unI encoder
, KnownNat ( SuperRecord.RecSize flds ) decoder = fmap I decoder
)
=> Serialisable ( Super.Rec flds ) where
encoder :: forall f. Monad f => JSON.Encoder f ( Super.Rec flds )
encoder = contramap ( SuperRecord.reflectRec @( ConstC Serialisable ) keyVal ) ( JSON.Encoder.keyValueTupleFoldable JSON.Encoder.json )
where
keyVal :: forall k v. ( KnownSymbol k, Serialisable v ) => SuperRecord.FldProxy k -> v -> ( Text, Json )
keyVal _ v = let k = symbolVal' ( proxy# :: Proxy# k ) in ( Text.pack k, JSON.Encoder.runPureEncoder ( encoder @v ) v )
decoder :: forall m. Monad m => JSON.Decoder m ( Super.Rec flds ) instance ( RecordDicts kvs Serialisable )
decoder = SuperRecord.unsafeRecBuild @flds @flds @( ConstC Serialisable ) decodeAndWrite => Serialisable ( Record I kvs ) where
encoder :: forall f. Monad f => JSON.Encoder f ( Rec kvs )
encoder = contramap encodeFields ( JSON.Encoder.keyValueTupleFoldable JSON.Encoder.json )
where where
decodeAndWrite encodeFields :: Record I kvs -> [ ( Text, Json ) ]
:: forall k v encodeFields = Rec.collapse . cmapWithKey (Proxy @Serialisable) keyVal
. ( KnownSymbol k, Serialisable v ) keyVal :: (Serialisable x, KnownSymbol k) => Proxy k -> I x -> K (Text, Json) x
=> SuperRecord.FldProxy k -> Proxy# v keyVal k (I x) = K ( Text.pack $ symbolVal k, JSON.Encoder.runPureEncoder encoder x )
-> JSON.Decoder m v
decodeAndWrite _ _ = do decoder :: forall m. Monad m => JSON.Decoder m ( Rec kvs )
let decoder = cpureM (Proxy @Serialisable) decoder
k :: Text
k = Text.pack ( symbolVal' ( proxy# :: Proxy# k ) )
val <- JSON.Decoder.atKey k ( decoder @v @m )
pure val
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -498,19 +484,19 @@ decodeUniqueMap dec = Map.fromList . map ( view typed &&& id ) <$> JSON.Decoder.
encodePointData encodePointData
:: forall f flds brushParams :: forall f flds brushParams
. ( Applicative f . ( Applicative f
, brushParams ~ Super.Rec flds , brushParams ~ Rec flds
, Serialisable ( Super.Rec flds ) , Serialisable ( Rec flds )
) )
=> JSON.Encoder f ( PointData brushParams ) => JSON.Encoder f ( PointData brushParams )
encodePointData = JSON.Encoder.mapLikeObj \ ( PointData { pointCoords, brushParams } ) -> encodePointData = JSON.Encoder.mapLikeObj \ ( PointData { pointCoords, brushParams } ) ->
JSON.Encoder.atKey' "coords" ( encoder @( Point2D Double ) ) pointCoords JSON.Encoder.atKey' "coords" ( encoder @( Point2D Double ) ) pointCoords
. JSON.Encoder.atKey' "brushParams" ( encoder @( Super.Rec flds ) ) brushParams . JSON.Encoder.atKey' "brushParams" ( encoder @( Rec flds ) ) brushParams
decodePointData decodePointData
:: forall m flds brushParams :: forall m flds brushParams
. ( Monad m . ( Monad m
, brushParams ~ Super.Rec flds , brushParams ~ Rec flds
, Serialisable ( Super.Rec flds ) , Serialisable ( Rec flds )
) )
=> JSON.Decoder m ( PointData brushParams ) => JSON.Decoder m ( PointData brushParams )
decodePointData = do decodePointData = do
@ -518,7 +504,7 @@ decodePointData = do
let let
pointState :: FocusState pointState :: FocusState
pointState = Normal pointState = Normal
brushParams <- JSON.Decoder.atKey "brushParams" ( decoder @( Super.Rec flds ) ) brushParams <- JSON.Decoder.atKey "brushParams" ( decoder @( Rec flds ) )
pure ( PointData { pointCoords, pointState, brushParams } ) pure ( PointData { pointCoords, pointState, brushParams } )
@ -549,7 +535,7 @@ encodeSomeSType = JSON.Encoder.mapLikeObj \ ( SomeSType ( _ :: Proxy# ty ) ) ->
sTySpline@STySpline | ( _ :: SType ( SplinePts clo ) ) <- sTySpline sTySpline@STySpline | ( _ :: SType ( SplinePts clo ) ) <- sTySpline
-> JSON.Encoder.atKey' "tag" JSON.Encoder.text "spline" -> JSON.Encoder.atKey' "tag" JSON.Encoder.text "spline"
. JSON.Encoder.atKey' "closed" JSON.Encoder.bool ( case ssplineType @clo of { SOpen -> False; SClosed -> True } ) . JSON.Encoder.atKey' "closed" JSON.Encoder.bool ( case ssplineType @clo of { SOpen -> False; SClosed -> True } )
sTyRecord@STyWithFn | ( _ :: SType ( AdaptableFunction kvs res ) ) <- sTyRecord sTyRecord@STyWithFn | ( _ :: SType ( WithParams kvs res ) ) <- sTyRecord
-> JSON.Encoder.atKey' "tag" JSON.Encoder.text "adaptableFun" -> JSON.Encoder.atKey' "tag" JSON.Encoder.text "adaptableFun"
. JSON.Encoder.atKey' "fields" encodeFieldTypes ( someSTypes @kvs ) . JSON.Encoder.atKey' "fields" encodeFieldTypes ( someSTypes @kvs )
. JSON.Encoder.atKey' "res" encodeSomeSType ( SomeSType ( proxy# :: Proxy# res ) ) . JSON.Encoder.atKey' "res" encodeSomeSType ( SomeSType ( proxy# :: Proxy# res ) )
@ -626,7 +612,7 @@ decodeFieldTypes = do
encodeBrush :: Applicative f => JSON.Encoder f ( Brush brushFields ) encodeBrush :: Applicative f => JSON.Encoder f (Brush brushFields)
encodeBrush = JSON.Encoder.mapLikeObj encodeBrush = JSON.Encoder.mapLikeObj
\ ( BrushData { brushName, brushCode } ) -> \ ( BrushData { brushName, brushCode } ) ->
JSON.Encoder.atKey' "name" JSON.Encoder.text brushName JSON.Encoder.atKey' "name" JSON.Encoder.text brushName
@ -649,7 +635,7 @@ encodeStroke = JSON.Encoder.mapLikeObj
\ ( Stroke \ ( Stroke
{ strokeName { strokeName
, strokeVisible , strokeVisible
, strokeSpline = strokeSpline :: StrokeSpline clo ( Super.Rec pointFields ) , strokeSpline = strokeSpline :: StrokeSpline clo ( Rec pointFields )
, strokeBrush , strokeBrush
} }
) -> ) ->
@ -662,7 +648,7 @@ encodeStroke = JSON.Encoder.mapLikeObj
mbEncodeBrush = case strokeBrush of mbEncodeBrush = case strokeBrush of
Nothing -> Nothing ->
id id
Just ( AdaptedBrush brush ) -> Just brush ->
JSON.Encoder.atKey' "brush" encodeBrush brush JSON.Encoder.atKey' "brush" encodeBrush brush
in in
JSON.Encoder.atKey' "name" JSON.Encoder.text strokeName JSON.Encoder.atKey' "name" JSON.Encoder.text strokeName
@ -679,22 +665,22 @@ decodeStroke uniqueSupply = do
strokeUnique <- lift ( liftIO . STM.atomically $ runReaderT freshUnique uniqueSupply ) strokeUnique <- lift ( liftIO . STM.atomically $ runReaderT freshUnique uniqueSupply )
strokeClosed <- JSON.Decoder.atKey "closed" JSON.Decoder.bool strokeClosed <- JSON.Decoder.atKey "closed" JSON.Decoder.bool
SomeBrushFields ( _ :: Proxy# pointFields ) <- JSON.Decoder.atKey "pointFields" decodeFieldTypes SomeBrushFields ( _ :: Proxy# pointFields ) <- JSON.Decoder.atKey "pointFields" decodeFieldTypes
mbBrush <- JSON.Decoder.atKeyOptional "brush" ( decodeBrush uniqueSupply ) mbSomeBrush <- JSON.Decoder.atKeyOptional "brush" ( decodeBrush uniqueSupply )
let
strokeBrush :: Maybe ( BrushAdaptedTo pointFields )
strokeBrush = case mbBrush of
Nothing
-> Nothing
Just ( SomeBrush ( brush@( BrushData {} ) ) )
-> Just $ adaptBrush @pointFields brush
if strokeClosed if strokeClosed
then do then do
strokeSpline <- JSON.Decoder.atKey "spline" ( decodeSpline @Closed @( PointData ( Super.Rec pointFields ) ) decodePointData ) strokeSpline <- JSON.Decoder.atKey "spline" ( decodeSpline @Closed @( PointData ( Rec pointFields ) ) decodePointData )
pure ( Stroke { strokeName, strokeVisible, strokeUnique, strokeSpline, strokeBrush } ) pure $ case mbSomeBrush of
Nothing ->
Stroke { strokeName, strokeVisible, strokeUnique, strokeSpline, strokeBrush = Nothing :: Maybe ( Brush '[] ) }
Just (SomeBrush brush) ->
Stroke { strokeName, strokeVisible, strokeUnique, strokeSpline, strokeBrush = Just brush }
else do else do
strokeSpline <- JSON.Decoder.atKey "spline" ( decodeSpline @Open @( PointData ( Super.Rec pointFields ) ) decodePointData ) strokeSpline <- JSON.Decoder.atKey "spline" ( decodeSpline @Open @( PointData ( Rec pointFields ) ) decodePointData )
pure ( Stroke { strokeName, strokeVisible, strokeUnique, strokeSpline, strokeBrush } ) pure $ case mbSomeBrush of
Nothing ->
Stroke { strokeName, strokeVisible, strokeUnique, strokeSpline, strokeBrush = Nothing :: Maybe ( Brush '[] ) }
Just (SomeBrush brush) ->
Stroke { strokeName, strokeVisible, strokeUnique, strokeSpline, strokeBrush = Just brush }
encodeStrokeHierarchy :: Monad f => JSON.Encoder f StrokeHierarchy encodeStrokeHierarchy :: Monad f => JSON.Encoder f StrokeHierarchy

View file

@ -1,21 +1,14 @@
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableInstances #-}
module MetaBrush.Document.Serialise module MetaBrush.Document.Serialise
( Workaround(..), workaround, Serialisable(..) ) ( Serialisable(..) )
where where
-- base -- large-anon
import GHC.TypeNats import Data.Record.Anonymous
( KnownNat ) ( Record, RecordDicts, I )
-- superrecord
import qualified SuperRecord as Super
( Rec )
import qualified SuperRecord
( RecApply, RecSize, UnsafeRecBuild )
import SuperRecord
( ConstC )
-- waargonaut -- waargonaut
import qualified Waargonaut.Decode as JSON import qualified Waargonaut.Decode as JSON
@ -29,10 +22,6 @@ import Math.Vector2D
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
data Workaround = Workaround
workaround :: Workaround -> Workaround
class Serialisable a where class Serialisable a where
encoder :: Monad f => JSON.Encoder f a encoder :: Monad f => JSON.Encoder f a
decoder :: Monad m => JSON.Decoder m a decoder :: Monad m => JSON.Decoder m a
@ -43,8 +32,5 @@ instance Serialisable a => Serialisable ( Point2D a )
instance Serialisable a => Serialisable ( Vector2D a ) instance Serialisable a => Serialisable ( Vector2D a )
instance ( SuperRecord.RecApply flds flds ( ConstC Serialisable ) instance ( RecordDicts kvs Serialisable )
, SuperRecord.UnsafeRecBuild flds flds ( ConstC Serialisable ) => Serialisable ( Record I kvs ) where
, KnownNat ( SuperRecord.RecSize flds )
)
=> Serialisable ( Super.Rec flds )

View file

@ -64,7 +64,7 @@ import MetaBrush.Document
, PointData(..), DiffPointData(..) , PointData(..), DiffPointData(..)
, coords, _strokeSpline , coords, _strokeSpline
) )
import MetaBrush.MetaParameter.Interpolation import MetaBrush.DSL.Interpolation
( Interpolatable(Diff) ) ( Interpolatable(Diff) )
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View file

@ -1,142 +0,0 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilyDependencies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module MetaBrush.MetaParameter.Interpolation
( Interpolatable(..)
, MapDiff, HasDiff', HasTorsor
)
where
-- base
import Data.Functor.Identity
( Identity(..) )
import Data.Kind
( Type )
import Data.Monoid
( Sum )
import GHC.TypeLits
( Symbol )
-- acts
import Data.Act
( Act(..), Torsor(..) )
-- groups
import Data.Group
( Group(..) )
-- superrecord
import qualified SuperRecord as Super
( Rec )
import qualified SuperRecord
( (:=), Has, RecTy, RecApply(..), UnsafeRecBuild(..), TraversalC, traverseC
, get, set, modify
)
import SuperRecord
( ConstC, Tuple22C )
-- MetaBrush
import Math.Module
( Module(..) )
import Math.Vector2D
( Point2D, Vector2D )
--------------------------------------------------------------------------------
class ( Module Double ( Diff a ), Torsor ( Diff a ) a ) => Interpolatable a where
type Diff a = ( d :: Type ) | d -> a
instance ( a ~ Double ) => Interpolatable ( Point2D a ) where
type Diff ( Point2D a ) = Vector2D a
instance Interpolatable Double where
type Diff Double = Sum Double
instance ( dvs ~ MapDiff kvs
, SuperRecord.UnsafeRecBuild dvs dvs ( ConstC Monoid )
, SuperRecord.RecApply dvs dvs ( Tuple22C ( ConstC ( Module Double ) ) ( SuperRecord.Has dvs ) )
, SuperRecord.RecApply dvs dvs ( Tuple22C ( ConstC Semigroup ) ( SuperRecord.Has dvs ) )
, SuperRecord.RecApply dvs dvs ( Tuple22C ( ConstC Group ) ( SuperRecord.Has dvs ) )
, SuperRecord.RecApply dvs dvs ( HasDiff' kvs )
, SuperRecord.TraversalC ( HasTorsor kvs ) kvs dvs
, Module Double ( Super.Rec ( MapDiff kvs ) )
)
=> Interpolatable ( Super.Rec kvs )
where
type Diff ( Super.Rec kvs ) = Super.Rec ( MapDiff kvs )
type family MapDiff ( kvs :: [ Type ] ) = ( lvs :: [ Type ] ) | lvs -> kvs where
MapDiff '[] = '[]
MapDiff ( k SuperRecord.:= v ': kvs ) = ( k SuperRecord.:= Diff v ': MapDiff kvs )
instance ( Monoid ( Super.Rec kvs )
, SuperRecord.RecApply kvs kvs
( Tuple22C ( ConstC Group ) ( SuperRecord.Has kvs ) )
)
=> Group ( Super.Rec kvs )
where
invert r = SuperRecord.recApply @kvs @kvs @( Tuple22C ( ConstC Group ) ( SuperRecord.Has kvs ) )
( \ lbl v res -> SuperRecord.set lbl ( invert v ) res ) r r
instance ( SuperRecord.RecApply kvs kvs
( Tuple22C ( ConstC ( Module Double ) ) ( SuperRecord.Has kvs ) )
, SuperRecord.UnsafeRecBuild kvs kvs ( ConstC ( Module Double ) )
)
=> Module Double ( Super.Rec kvs )
where
origin = runIdentity $ SuperRecord.unsafeRecBuild @kvs @kvs @( ConstC ( Module Double ) ) ( \ _ _ -> Identity origin )
r1 ^+^ r2 =
SuperRecord.recApply @kvs @kvs @( Tuple22C ( ConstC ( Module Double ) ) ( SuperRecord.Has kvs ) )
( \ lbl v1 res -> SuperRecord.modify lbl ( v1 ^+^ ) res ) r1 r2
r1 ^-^ r2 =
SuperRecord.recApply @kvs @kvs @( Tuple22C ( ConstC ( Module Double ) ) ( SuperRecord.Has kvs ) )
( \ lbl v1 res -> SuperRecord.modify lbl ( v1 ^-^ ) res ) r1 r2
k *^ r =
SuperRecord.recApply @kvs @kvs @( Tuple22C ( ConstC ( Module Double ) ) ( SuperRecord.Has kvs ) )
( \ lbl v1 res -> SuperRecord.set lbl ( k *^ v1 ) res ) r r
class ( SuperRecord.Has kvs k t, Interpolatable t, d ~ Diff t, Just t ~ SuperRecord.RecTy k kvs )
=> HasDiff ( kvs :: [ Type ] ) ( t :: Type ) ( k :: Symbol ) ( d :: Type )
instance ( SuperRecord.Has kvs k t, Interpolatable t, d ~ Diff t, Just t ~ SuperRecord.RecTy k kvs )
=> HasDiff kvs t k d
type family FromJust ( a :: Maybe k ) :: k where
FromJust ( Just a ) = a
class HasDiff kvs ( FromJust ( SuperRecord.RecTy k kvs ) ) k d => HasDiff' kvs k d
instance HasDiff kvs ( FromJust ( SuperRecord.RecTy k kvs ) ) k d => HasDiff' kvs k d
instance ( dvs ~ MapDiff kvs
, SuperRecord.RecApply dvs dvs ( Tuple22C ( ConstC Semigroup ) ( SuperRecord.Has dvs ) )
, SuperRecord.RecApply dvs dvs ( HasDiff' kvs )
)
=> Act ( Super.Rec dvs ) ( Super.Rec kvs )
where
ds as = SuperRecord.recApply @dvs @dvs @( HasDiff' kvs )
( \ lbl d1 res -> SuperRecord.modify lbl ( d1 ) res ) ds as
class ( d ~ Diff t, Torsor d t, SuperRecord.Has kvs k t ) => HasTorsor ( kvs :: [Type] ) ( k :: Symbol ) t d where
instance ( d ~ Diff t, Torsor d t, SuperRecord.Has kvs k t ) => HasTorsor kvs k t d where
instance ( dvs ~ MapDiff kvs
, SuperRecord.TraversalC ( HasTorsor kvs ) kvs dvs
, Act ( Super.Rec dvs ) ( Super.Rec kvs )
, Group ( Super.Rec dvs )
)
=> Torsor ( Super.Rec dvs ) ( Super.Rec kvs ) where
as <-- bs =
runIdentity $ SuperRecord.traverseC @( HasTorsor kvs ) @Identity @kvs @dvs
( \ lbl a -> Identity ( a <-- SuperRecord.get lbl bs ) )
as

View file

@ -0,0 +1,192 @@
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module MetaBrush.Records where
-- base
import Data.Coerce
( coerce )
import Data.Functor.Const
( Const(..) )
import Data.Functor.Product
( Product(Pair) )
import Data.Kind
( Type )
import Data.List
( intersperse )
import Data.Monoid
( Endo(..) )
import Data.Proxy
( Proxy(..) )
import GHC.TypeLits
( Symbol, KnownSymbol, symbolVal
, SomeSymbol(..), someSymbolVal )
import GHC.Exts
( Any )
import GHC.Show
( showCommaSpace )
import Unsafe.Coerce
( unsafeCoerce )
-- containers
import Data.Map.Lazy as Map
( intersection, intersectionWith, intersectionWithKey
, union
)
-- deepseq
import Control.DeepSeq
( NFData(..) )
-- groups
import Data.Group
( Group(..) )
-- large-anon
import Data.Record.Anonymous
( Record , RecordDicts(..)
, Dict(..), I(..), K(..)
)
import Data.Record.Anonymous.Internal
( Record(MkR) )
import qualified Data.Record.Anonymous as Rec
( mapM, cpure, cmap, czipWith, collapse )
--------------------------------------------------------------------------------
-- This instance only uses RecordDicts and not generic metadata.
instance {-# OVERLAPPING #-} RecordDicts kvs Show => Show (Record I kvs) where
showsPrec d =
aux
. Rec.collapse
. cmapWithKey (Proxy @Show) showField
where
showField :: (KnownSymbol k, Show x) => Proxy k -> I x -> K ShowS x
showField k x = K $ showString (symbolVal k) . showString " = " . showsPrec 0 x
aux :: [ShowS] -> ShowS
aux fields = showParen (d >= 11) (
showString " {"
. foldr (.) id (intersperse showCommaSpace fields)
. showString "}"
)
data WithParams params a =
WithParams
{ defaultParams :: Rec params
, withParams :: Rec params -> a
}
type Rec :: [ ( Symbol, Type ) ] -> Type
type Rec = Record I
foldRec :: forall y f r. ( forall x . f x -> y -> y ) -> Record f r -> y -> y
foldRec f r = coerce $ Rec.mapM g r
where
g :: ( forall x. f x -> Const (Endo y) (I x) )
g x = coerce (f x)
instance RecordDicts kvs Semigroup
=> Semigroup (Record I kvs) where
(<>) = Rec.czipWith (Proxy @Semigroup) (<>)
instance ( RecordDicts kvs Semigroup
, RecordDicts kvs Monoid )
=> Monoid (Record I kvs) where
mempty = Rec.cpure (Proxy @Monoid) mempty
instance ( RecordDicts kvs Semigroup
, RecordDicts kvs Monoid
, RecordDicts kvs Group )
=> Group (Record I kvs) where
invert = Rec.cmap (Proxy @Group) ( \ (I g) -> I (invert g) )
instance RecordDicts kvs NFData
=> NFData ( Record I kvs ) where
rnf _ = () -- TODO
data MyIntersection r1 g r2 c where
MyIntersection
:: forall i r1 g r2 c
. ( RecordDicts i c )
=> { myProject :: forall f. Record f r1 -> Record (f `Product` g) i
, myInject :: Record g i -> Record g r2
}
-> MyIntersection r1 g r2 c
myIntersect
:: forall c r1 g r2
. ( RecordDicts r1 c )
=> Record g r2
-> MyIntersection r1 g r2 c
myIntersect (MkR r2) =
proveRecordDicts @c @Any intersectionDict
( MyIntersection { myProject, myInject } )
where
myProject :: Record f r1 -> Record (f `Product` g) Any
myProject (MkR r1) = MkR (Map.intersectionWith Pair r1 r2)
myInject :: Record g Any -> Record g r2
myInject (MkR i) = MkR (Map.union i r2)
intersectionDict :: Record (Dict c) Any
intersectionDict =
case recordDicts @r1 @c Proxy of
MkR d -> MkR (Map.intersection d r2)
cpureM ::
(Applicative m, RecordDicts r c)
=> Proxy c
-> (forall x. c x => m (f x))
-> m (Record f r)
cpureM p f = Rec.mapM (\Dict -> f) (recordDicts p)
cmapWithKey ::
forall c r f g
. RecordDicts r c
=> Proxy c
-> (forall k x. (c x, KnownSymbol k) => Proxy k -> f x -> g x)
-> Record f r
-> Record g r
cmapWithKey p f =
zipWithKey ( \ px Dict x -> f px x ) (recordDicts p)
zipWithKey ::
forall r f g h
. ( forall k x. KnownSymbol k => Proxy k -> f x -> g x -> h x )
-> Record f r -> Record g r -> Record h r
zipWithKey f (MkR a) (MkR b) = MkR $
Map.intersectionWithKey g a b
where
g :: String -> f x -> g x -> h x
g s = case someSymbolVal s of
SomeSymbol px -> f px
proveRecordDicts :: forall c r x. Record (Dict c) r -> (RecordDicts r c => x) -> x
proveRecordDicts r f = case myDict of { MyDict -> f }
where
myDict :: MyDict r c
myDict = unsafeCoerce ( MyDict' $ RecordDictsDict ( const $ unsafeCoerce r ) )
-- Dictionary passing nonsense.
newtype RecordDictsDict r c
= RecordDictsDict (Proxy c -> Record (Dict c) r)
data MyDict r c where
MyDict :: RecordDicts r c => MyDict r c
data MyDict' r c where
MyDict' :: RecordDictsDict r c -> MyDict' r c

View file

@ -8,11 +8,11 @@
{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-} {-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-} {-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE NegativeLiterals #-} {-# LANGUAGE NegativeLiterals #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
@ -33,10 +33,10 @@ import Data.Foldable
( for_, sequenceA_, traverse_ ) ( for_, sequenceA_, traverse_ )
import Data.Functor.Compose import Data.Functor.Compose
( Compose(..) ) ( Compose(..) )
import Data.Functor.Product
( Product(..) )
import Data.Int import Data.Int
( Int32 ) ( Int32 )
import GHC.Exts
( Proxy#, proxy# )
import GHC.Generics import GHC.Generics
( Generic, Generic1 ) ( Generic, Generic1 )
@ -65,16 +65,19 @@ import Generic.Data
-- gi-cairo-render -- gi-cairo-render
import qualified GI.Cairo.Render as Cairo import qualified GI.Cairo.Render as Cairo
-- large-anon
import Data.Record.Anonymous
( Record
, I
)
import qualified Data.Record.Anonymous as Rec
( map )
-- lens -- lens
import Control.Lens import Control.Lens
( view ) ( view )
-- superrecord
import qualified SuperRecord as Super
( Rec )
import qualified SuperRecord
( Intersect )
-- transformers -- transformers
import Control.Monad.Trans.Class import Control.Monad.Trans.Class
( lift ) ( lift )
@ -104,7 +107,7 @@ import Math.Vector2D
import MetaBrush.Asset.Colours import MetaBrush.Asset.Colours
( Colours, ColourRecord(..) ) ( Colours, ColourRecord(..) )
import MetaBrush.Brush import MetaBrush.Brush
( Brush(..), BrushAdaptedTo(..) ) ( Brush(..) )
import MetaBrush.Context import MetaBrush.Context
( Modifier(..) ( Modifier(..)
, HoldAction(..), PartialPath(..) , HoldAction(..), PartialPath(..)
@ -128,10 +131,12 @@ import MetaBrush.Document.Serialise
( ) -- 'Serialisable' instances ( ) -- 'Serialisable' instances
import MetaBrush.Document.Update import MetaBrush.Document.Update
( DocChange(..) ) ( DocChange(..) )
import MetaBrush.MetaParameter.AST import MetaBrush.DSL.Interpolation
( AdaptableFunction(..) ) ( Interpolatable, DRec )
import MetaBrush.MetaParameter.Interpolation import MetaBrush.Records
( MapDiff ) ( Rec, WithParams(..)
, MyIntersection (..), myIntersect
)
import MetaBrush.UI.ToolBar import MetaBrush.UI.ToolBar
( Mode(..) ) ( Mode(..) )
import MetaBrush.Unique import MetaBrush.Unique
@ -210,9 +215,9 @@ getDocumentRender
, Just finalPoint <- mbFinalPoint , Just finalPoint <- mbFinalPoint
, let , let
previewStroke :: Stroke previewStroke :: Stroke
previewStroke = withAnchorBrushData anchor doc \ mbBrush ( pointData :: Super.Rec pointFields ) -> previewStroke = withAnchorBrushData anchor doc \ mbBrush ( pointData :: Rec pointFields ) ->
let let
previewSpline :: Spline Open ( CachedStroke RealWorld ) ( PointData ( Super.Rec pointFields ) ) previewSpline :: Spline Open ( CachedStroke RealWorld ) ( PointData ( Rec pointFields ) )
previewSpline = catMaybesSpline ( invalidateCache undefined ) previewSpline = catMaybesSpline ( invalidateCache undefined )
( PointData p0 Normal pointData ) ( PointData p0 Normal pointData )
( do ( do
@ -300,30 +305,42 @@ instance NFData StrokeRenderData where
strokeRenderData :: FitParameters -> Stroke -> Maybe ( ST RealWorld StrokeRenderData ) strokeRenderData :: FitParameters -> Stroke -> Maybe ( ST RealWorld StrokeRenderData )
strokeRenderData fitParams strokeRenderData fitParams
( Stroke ( Stroke
{ strokeSpline = spline :: StrokeSpline clo pointParams { strokeSpline = spline :: StrokeSpline clo ( Rec pointFields )
, strokeBrush = ( strokeBrush :: Maybe ( BrushAdaptedTo pointFields ) ) , strokeBrush = ( strokeBrush :: Maybe ( Brush brushFields ) )
, .. , ..
} }
) | strokeVisible ) | strokeVisible
= Just $ case strokeBrush of = Just $ case strokeBrush of
Just ( AdaptedBrush ( brush :: Brush brushFields ) ) Just ( BrushData { brushFunction = fn } )
| ( _ :: Proxy# usedFields ) <- ( proxy# :: Proxy# ( brushFields `SuperRecord.Intersect` pointFields ) ) | WithParams
-- Get the adaptable brush shape (function), { defaultParams = brush_defaults
-- specialising it to the type we are using. , withParams = brushFn
, let } <- fn
toUsedParams :: Super.Rec pointFields -> Super.Rec usedFields
brushShapeFn :: Super.Rec usedFields -> SplinePts Closed
AdaptableFunction ( toUsedParams, brushShapeFn ) = brushFunction brush
-> do -> do
-- Use the handy 'intersect' function to do a computation
-- using only the relevant fields (which are the intersection
-- of the parameters along the stroke and the brush parameters).
--
-- See also MetaBrush.DSL.Eval.eval for how we interpret brush code
-- to obtain a brush function.
case myIntersect @Interpolatable @pointFields brush_defaults of
MyIntersection
{ myProject = project :: forall f. Record f pointFields -> Record (f `Product` I) usedFields
, myInject } -> do
let
toUsedParams :: Rec pointFields -> Rec usedFields
toUsedParams given = Rec.map ( \ (Pair x _ ) -> x ) $ project @I given
embedUsedParams :: Rec usedFields -> Rec brushFields
embedUsedParams = myInject
-- Compute the outline using the brush function. -- Compute the outline using the brush function.
( outline, fitPts ) <- ( outline, fitPts ) <-
computeStrokeOutline @( Super.Rec ( MapDiff usedFields ) ) @clo @( Super.Rec usedFields ) computeStrokeOutline @( DRec usedFields ) @clo @( Rec usedFields )
fitParams ( toUsedParams . brushParams ) brushShapeFn spline fitParams ( toUsedParams . brushParams ) ( brushFn . embedUsedParams ) spline
pure $ pure $
StrokeWithOutlineRenderData StrokeWithOutlineRenderData
{ strokeDataSpline = spline { strokeDataSpline = spline
, strokeOutlineData = ( outline, fitPts ) , strokeOutlineData = ( outline, fitPts )
, strokeBrushFunction = brushShapeFn . toUsedParams , strokeBrushFunction = brushFn . embedUsedParams . toUsedParams
} }
_ -> pure $ _ -> pure $
StrokeRenderData StrokeRenderData

View file

@ -178,7 +178,8 @@ coords = view typed
computeStrokeOutline :: computeStrokeOutline ::
forall diffParams ( clo :: SplineType ) brushParams crvData ptData s forall diffParams ( clo :: SplineType ) brushParams crvData ptData s
. ( KnownSplineType clo . ( KnownSplineType clo
, Group diffParams, Module Double diffParams , Group diffParams
, Module Double diffParams
, Torsor diffParams brushParams , Torsor diffParams brushParams
, HasType ( Point2D Double ) ptData , HasType ( Point2D Double ) ptData
, HasType ( CachedStroke s ) crvData , HasType ( CachedStroke s ) crvData