symantic-parser-0.1.0.20210201: src/Symantic/Parser/Machine/View.hs
{-# LANGUAGE UndecidableInstances #-} -- For ShowLetName
module Symantic.Parser.Machine.View where
import Data.Bool (Bool(..))
import Data.Function (($), (.), id)
import Data.Functor ((<$>))
import Data.Kind (Type)
import Data.Semigroup (Semigroup(..))
import Data.String (String, IsString(..))
import Text.Show (Show(..))
import qualified Data.Tree as Tree
import qualified Data.List as List
import qualified Language.Haskell.TH.Syntax as TH
import Symantic.Parser.Grammar.ObserveSharing (ShowLetName(..))
import Symantic.Parser.Machine.Instructions
-- * Type 'ViewMachine'
newtype ViewMachine (showName::Bool) inp (vs:: [Type]) (es::Peano) a
= ViewMachine { unViewMachine ::
Tree.Forest String -> Tree.Forest String }
viewMachine ::
ViewMachine sN inp vs es a ->
ViewMachine sN inp vs es a
viewMachine = id
-- | Helper to view a command.
viewInstrCmd :: String -> Tree.Forest String -> Tree.Tree String
viewInstrCmd n = Tree.Node n
-- | Helper to view an argument.
viewInstrArg :: String -> Tree.Forest String -> Tree.Tree String
viewInstrArg n = Tree.Node ("<"<>n<>">")
instance Show (ViewMachine sN inp vs es a) where
show = drawTree . Tree.Node "" . ($ []) . unViewMachine
where
drawTree :: Tree.Tree String -> String
drawTree = List.unlines . draw
draw :: Tree.Tree String -> [String]
draw (Tree.Node x ts0) = List.lines x <> drawSubTrees ts0
where
drawSubTrees [] = []
drawSubTrees [t] = shift "" " " (draw t)
drawSubTrees (t:ts) = shift "" "| " (draw t) <> drawSubTrees ts
shift first other = List.zipWith (<>) (first : List.repeat other)
instance IsString (ViewMachine sN inp vs es a) where
fromString s = ViewMachine $ \is -> Tree.Node (fromString s) [] : is
instance Stackable (ViewMachine sN) where
push a k = ViewMachine $ \is -> viewInstrCmd ("push "<>showsPrec 10 a "") [] : unViewMachine k is
pop k = ViewMachine $ \is -> viewInstrCmd "pop" [] : unViewMachine k is
liftI2 f k = ViewMachine $ \is -> viewInstrCmd ("lift "<>showsPrec 10 f "") [] : unViewMachine k is
swap k = ViewMachine $ \is -> viewInstrCmd "swap" [] : unViewMachine k is
instance Branchable (ViewMachine sN) where
caseI l r = ViewMachine $ \is -> viewInstrCmd "case"
[ viewInstrArg "left" (unViewMachine l [])
, viewInstrArg "right" (unViewMachine r [])
] : is
choices ps bs d = ViewMachine $ \is ->
viewInstrCmd ("choices "<>show ps) (
(viewInstrArg "branch" . ($ []) . unViewMachine <$> bs) <>
[ viewInstrArg "default" (unViewMachine d []) ]
) : is
instance Failable (ViewMachine sN) where
fail _err = ViewMachine $ \is -> viewInstrCmd "fail" [] : is
popFail k = ViewMachine $ \is -> viewInstrCmd "popFail" [] : unViewMachine k is
catchFail t h = ViewMachine $ \is -> viewInstrCmd "catchFail"
[ viewInstrArg "try" (unViewMachine t [])
, viewInstrArg "handler" (unViewMachine h [])
] : is
instance Inputable (ViewMachine sN) where
loadInput k = ViewMachine $ \is -> viewInstrCmd "loadInput" [] : unViewMachine k is
pushInput k = ViewMachine $ \is -> viewInstrCmd "pushInput" [] : unViewMachine k is
instance
ShowLetName sN TH.Name =>
Routinable (ViewMachine sN) where
subroutine (LetName n) sub k = ViewMachine $ \is ->
Tree.Node (showLetName @sN n<>":") (unViewMachine sub [])
: unViewMachine k is
jump (LetName n) = ViewMachine $ \is -> viewInstrCmd ("jump "<>showLetName @sN n) [] : is
call (LetName n) k = ViewMachine $ \is -> viewInstrCmd ("call "<>showLetName @sN n) [] : unViewMachine k is
ret = ViewMachine $ \is -> viewInstrCmd "ret" [] : is
instance
ShowLetName sN TH.Name =>
Joinable (ViewMachine sN) where
defJoin (LetName n) j k = ViewMachine $ \is ->
Tree.Node (showLetName @sN n<>":") (unViewMachine j [])
: unViewMachine k is
refJoin (LetName n) = ViewMachine $ \is -> viewInstrCmd ("refJoin "<>showLetName @sN n) [] : is
instance Readable tok (ViewMachine sN) where
read _es p k = ViewMachine $ \is -> viewInstrCmd ("read "<>showsPrec 10 p "") [] : unViewMachine k is