1 {-# LANGUAGE PatternSynonyms #-} -- For Instr
 
   2 {-# LANGUAGE ViewPatterns #-} -- For unSomeInstr
 
   3 -- | Initial encoding with bottom-up optimizations of 'Instr'uctions,
 
   4 -- re-optimizing downward as needed after each optimization.
 
   5 -- There is only one optimization (for 'pushValue') so far,
 
   6 -- but the introspection enabled by the 'Instr' data-type
 
   7 -- is also useful to optimize with more context in the 'Machine'.
 
   8 module Symantic.Parser.Machine.Optimize where
 
  10 import Data.Bool (Bool(..))
 
  11 import Data.Either (Either)
 
  12 import Data.Maybe (Maybe(..))
 
  13 import Data.Function ((.))
 
  14 import Data.Kind (Constraint)
 
  15 import Data.Proxy (Proxy(..))
 
  16 import GHC.TypeLits (KnownSymbol)
 
  17 import Type.Reflection (Typeable, typeRep, eqTypeRep, (:~~:)(..))
 
  18 import qualified Data.Functor as Functor
 
  19 import qualified Language.Haskell.TH as TH
 
  21 import Symantic.Parser.Grammar
 
  22 import Symantic.Parser.Machine.Input
 
  23 import Symantic.Parser.Machine.Instructions
 
  24 import Symantic.Univariant.Trans
 
  26 -- * Data family 'Instr'
 
  27 -- | 'Instr'uctions of the 'Machine'.
 
  28 -- This is an extensible data-type.
 
  30   (instr :: ReprInstr -> Constraint)
 
  34 -- | Convenient utility to pattern-match a 'SomeInstr'.
 
  35 pattern Instr :: Typeable comb =>
 
  36   Instr comb repr inp vs a ->
 
  37   SomeInstr repr inp vs a
 
  38 pattern Instr x <- (unSomeInstr -> Just x)
 
  40 -- ** Type 'SomeInstr'
 
  41 -- | Some 'Instr'uction existentialized over the actual instruction symantic class.
 
  42 -- Useful to handle a list of 'Instr'uctions
 
  43 -- without requiring impredicative quantification.
 
  44 -- Must be used by pattern-matching
 
  45 -- on the 'SomeInstr' data-constructor,
 
  46 -- to bring the constraints in scope.
 
  48 -- As in 'SomeComb', a first pass of optimizations
 
  49 -- is directly applied in it
 
  50 -- to avoid introducing an extra newtype,
 
  51 -- this also give a more undestandable code.
 
  52 data SomeInstr repr inp vs a =
 
  54   ( Trans (Instr instr repr inp vs) (repr inp vs)
 
  57   SomeInstr (Instr instr repr inp vs a)
 
  59 instance Trans (SomeInstr repr inp vs) (repr inp vs) where
 
  60   trans (SomeInstr x) = trans x
 
  62 -- | @(unSomeInstr i :: 'Maybe' ('Instr' comb repr inp vs a))@
 
  63 -- extract the data-constructor from the given 'SomeInstr'
 
  64 -- iif. it belongs to the @('Instr' comb repr a)@ data-instance.
 
  66   forall instr repr inp vs a.
 
  68   SomeInstr repr inp vs a ->
 
  69   Maybe (Instr instr repr inp vs a)
 
  70 unSomeInstr (SomeInstr (i::Instr i repr inp vs a)) =
 
  71   case typeRep @instr `eqTypeRep` typeRep @i of
 
  76 data instance Instr InstrValuable repr inp vs a where
 
  79     SomeInstr repr inp (v ': vs) a ->
 
  80     Instr InstrValuable repr inp vs a
 
  82     SomeInstr repr inp vs a ->
 
  83     Instr InstrValuable repr inp (v ': vs) a
 
  85     TermInstr (x -> y -> z) ->
 
  86     SomeInstr repr inp (z : vs) a ->
 
  87     Instr InstrValuable repr inp (y : x : vs) a
 
  89     SomeInstr repr inp (x ': y ': vs) a ->
 
  90     Instr InstrValuable repr inp (y ': x ': vs) a
 
  91 instance InstrValuable repr => Trans (Instr InstrValuable repr inp vs) (repr inp vs) where
 
  93     PushValue x k -> pushValue x (trans k)
 
  94     PopValue k -> popValue (trans k)
 
  95     Lift2Value f k -> lift2Value f (trans k)
 
  96     SwapValue k -> swapValue (trans k)
 
  97 instance InstrValuable repr => InstrValuable (SomeInstr repr) where
 
  98   pushValue _v (Instr (PopValue i)) = i
 
  99   pushValue v i = SomeInstr (PushValue v i)
 
 100   popValue = SomeInstr . PopValue
 
 101   lift2Value f = SomeInstr . Lift2Value f
 
 102   swapValue = SomeInstr . SwapValue
 
 104 -- InstrExceptionable
 
 105 data instance Instr InstrExceptionable repr inp vs a where
 
 109     [ErrorItem (InputToken inp)] ->
 
 110     Instr InstrExceptionable repr inp vs a
 
 114     SomeInstr repr inp vs ret ->
 
 115     Instr InstrExceptionable repr inp vs ret
 
 119     SomeInstr repr inp vs ret ->
 
 120     SomeInstr repr inp (Cursor inp ': vs) ret ->
 
 121     Instr InstrExceptionable repr inp vs ret
 
 122 instance InstrExceptionable repr => Trans (Instr InstrExceptionable repr inp vs) (repr inp vs) where
 
 124     RaiseException lbl err -> raiseException lbl err
 
 125     PopException lbl k -> popException lbl (trans k)
 
 126     CatchException lbl l r -> catchException lbl (trans l) (trans r)
 
 127 instance InstrExceptionable repr => InstrExceptionable (SomeInstr repr) where
 
 128   raiseException lbl = SomeInstr . RaiseException lbl
 
 129   popException lbl = SomeInstr . PopException lbl
 
 130   catchException lbl x = SomeInstr . CatchException lbl x
 
 133 data instance Instr InstrBranchable repr inp vs a where
 
 135     SomeInstr repr inp (x ': vs) a ->
 
 136     SomeInstr repr inp (y ': vs) a ->
 
 137     Instr InstrBranchable repr inp (Either x y ': vs) a
 
 139     [TermInstr (v -> Bool)] ->
 
 140     [SomeInstr repr inp vs a] ->
 
 141     SomeInstr repr inp vs a ->
 
 142     Instr InstrBranchable repr inp (v ': vs) a
 
 143 instance InstrBranchable repr => Trans (Instr InstrBranchable repr inp vs) (repr inp vs) where
 
 145     CaseBranch l r -> caseBranch (trans l) (trans r)
 
 146     ChoicesBranch ps bs d -> choicesBranch ps (trans Functor.<$> bs) (trans d)
 
 147 instance InstrBranchable repr => InstrBranchable (SomeInstr repr) where
 
 148   caseBranch l = SomeInstr . CaseBranch l
 
 149   choicesBranch ps bs = SomeInstr . ChoicesBranch ps bs
 
 152 data instance Instr InstrCallable repr inp vs a where
 
 154     LetBindings TH.Name (SomeInstr repr inp '[]) ->
 
 155     SomeInstr repr inp vs a ->
 
 156     Instr InstrCallable repr inp vs a
 
 159     SomeInstr repr inp (v ': vs) a ->
 
 160     Instr InstrCallable repr inp vs a
 
 162     Instr InstrCallable repr inp '[a] a
 
 165     Instr InstrCallable repr inp '[] a
 
 166 instance InstrCallable repr => Trans (Instr InstrCallable repr inp vs) (repr inp vs) where
 
 168     DefLet subs k -> defLet ((\(SomeLet sub) -> SomeLet (trans sub)) Functor.<$> subs) (trans k)
 
 170     Call n k -> call n (trans k)
 
 172 instance InstrCallable repr => InstrCallable (SomeInstr repr) where
 
 173   defLet subs = SomeInstr . DefLet subs
 
 174   jump = SomeInstr . Jump
 
 175   call n = SomeInstr . Call n
 
 179 data instance Instr InstrJoinable repr inp vs a where
 
 182     SomeInstr repr inp (v ': vs) a ->
 
 183     SomeInstr repr inp vs a ->
 
 184     Instr InstrJoinable repr inp vs a
 
 187     Instr InstrJoinable repr inp (v ': vs) a
 
 188 instance InstrJoinable repr => Trans (Instr InstrJoinable repr inp vs) (repr inp vs) where
 
 190     DefJoin n sub k -> defJoin n (trans sub) (trans k)
 
 191     RefJoin n -> refJoin n
 
 192 instance InstrJoinable repr => InstrJoinable (SomeInstr repr) where
 
 193   defJoin n sub = SomeInstr . DefJoin n sub
 
 194   refJoin = SomeInstr . RefJoin
 
 197 data instance Instr InstrInputable repr inp vs a where
 
 199     SomeInstr repr inp (Cursor inp ': vs) a ->
 
 200     Instr InstrInputable repr inp vs a
 
 202     SomeInstr repr inp vs a ->
 
 203     Instr InstrInputable repr inp (Cursor inp ': vs) a
 
 204 instance InstrInputable repr => Trans (Instr InstrInputable repr inp vs) (repr inp vs) where
 
 206     PushInput k -> pushInput (trans k)
 
 207     LoadInput k -> loadInput (trans k)
 
 208 instance InstrInputable repr => InstrInputable (SomeInstr repr) where
 
 209   pushInput = SomeInstr . PushInput
 
 210   loadInput = SomeInstr . LoadInput
 
 213 data instance Instr (InstrReadable tok) repr inp vs a where
 
 215     [ErrorItem (InputToken inp)] ->
 
 216     TermInstr (InputToken inp -> Bool) ->
 
 217     SomeInstr repr inp (InputToken inp ': vs) a ->
 
 218     Instr (InstrReadable tok) repr inp vs a
 
 220   ( InstrReadable tok repr, tok ~ InputToken inp ) =>
 
 221   Trans (Instr (InstrReadable tok) repr inp vs) (repr inp vs) where
 
 223     Read es p k -> read es p (trans k)
 
 225   ( InstrReadable tok repr, Typeable tok ) =>
 
 226   InstrReadable tok (SomeInstr repr) where
 
 227   read es p = SomeInstr . Read es p