From 01ce3d75986df7225d2e34011f57775d20fb77d8 Mon Sep 17 00:00:00 2001
From: Julien Moutinho <julm+symantic-parser@sourcephile.fr>
Date: Sat, 20 Jan 2024 00:06:12 +0100
Subject: [PATCH] impl: tweak viewing and writing

---
 src/Symantic/Parser/Grammar/Production.hs |  16 +-
 src/Symantic/Parser/Grammar/View.hs       |  23 ++-
 src/Symantic/Parser/Grammar/Write.hs      | 236 +++++++++++-----------
 src/Symantic/Parser/Machine/View.hs       |  14 +-
 4 files changed, 149 insertions(+), 140 deletions(-)

diff --git a/src/Symantic/Parser/Grammar/Production.hs b/src/Symantic/Parser/Grammar/Production.hs
index d726884..c86d278 100644
--- a/src/Symantic/Parser/Grammar/Production.hs
+++ b/src/Symantic/Parser/Grammar/Production.hs
@@ -33,6 +33,16 @@ data Production (vs :: [Type]) a where
   --ProdN :: Production vs (a->b) -> Production (a ': vs) b
   --ProdW :: Production vs b -> Production (a ': vs) b
 
+instance Show (Production '[] a) where
+  showsPrec p x = showsPrec p (normalOrderReduction (prodCode x))
+instance Show (SomeData TH.CodeQ a) where
+  -- The 'Derivable' constraint contained in 'SomeData'
+  -- is 'TH.CodeQ', hence 'Symantic.View' cannot be used here.
+  -- Fortunately 'TH.showCode' can be implemented.
+  showsPrec p = showString Fun.. TH.showCode p Fun.. derive
+
+
+
 data Prod a = Prod
   { prodI :: SomeData Identity a
   , prodQ :: SomeData TH.CodeQ a
@@ -109,12 +119,6 @@ prodCon name = do
            (TH.unsafeCodeCoerce (return (TH.ConE $(TH.lift n)))) |]
     _ -> error "[BUG]: impossible prodCon case"
 
-instance Show (SomeData TH.CodeQ a) where
-  -- The 'Derivable' constraint contained in 'SomeData'
-  -- is 'TH.CodeQ', hence 'Symantic.View' cannot be used here.
-  -- Fortunately 'TH.showCode' can be implemented.
-  showsPrec p = showString Fun.. TH.showCode p Fun.. derive
-
 unProdE :: Production '[] a -> Prod a
 unProdE t = case t of ProdE t' -> t'
 
diff --git a/src/Symantic/Parser/Grammar/View.hs b/src/Symantic/Parser/Grammar/View.hs
index 2f87a51..40d6a57 100644
--- a/src/Symantic/Parser/Grammar/View.hs
+++ b/src/Symantic/Parser/Grammar/View.hs
@@ -1,4 +1,6 @@
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE DeriveLift #-}
+{-# LANGUAGE StandaloneDeriving #-}
 module Symantic.Parser.Grammar.View where
 
 import Data.Bool (Bool)
@@ -14,22 +16,24 @@ import qualified Data.Functor as Functor
 import qualified Data.HashMap.Strict as HM
 import qualified Data.List as List
 import qualified Data.Tree as Tree
+import Prelude (undefined)
+import Control.DeepSeq (NFData(..))
 
 import Symantic.Semantics.SharingObserver
 import Symantic.Semantics.Data (normalOrderReduction)
 import Symantic.Parser.Grammar.Combinators
 import Symantic.Parser.Grammar.SharingObserver
 import qualified Symantic.Parser.Grammar.Production as Prod
+import qualified Language.Haskell.TH as TH
+import qualified Language.Haskell.TH.Syntax as TH
 
 -- * Type 'ViewGrammar'
 newtype ViewGrammar (showName::Bool) a = ViewGrammar { unViewGrammar :: Tree.Tree (String, String) }
+  deriving (NFData, TH.Lift)
 
 viewGrammar :: ViewGrammar sN a -> ViewGrammar sN a
 viewGrammar = id
 
-showProduction :: Prod.Production '[] a -> String
-showProduction p = showsPrec 10 (normalOrderReduction (Prod.prodCode p)) ""
-
 instance Show (ViewGrammar sN a) where
   show = List.unlines . draw . unViewGrammar
     where
@@ -48,11 +52,10 @@ instance CombAlternable (ViewGrammar sN) where
     ("<|>" <> if exn == ExceptionFailure then "" else ("^"<>show exn), "")
     [unViewGrammar x, unViewGrammar y]
   throw exn = ViewGrammar $ Tree.Node ("throw "<>show exn, "") []
-  failure _sf = ViewGrammar $ Tree.Node ("failure", "") []
   try x = ViewGrammar $ Tree.Node ("try", "") [unViewGrammar x]
 instance CombApplicable (ViewGrammar sN) where
   _f <$> x = ViewGrammar $ Tree.Node ("<$>", "") [unViewGrammar x]
-  pure a = ViewGrammar $ Tree.Node ("pure "<>showProduction a, "") []
+  pure a = ViewGrammar $ Tree.Node ("pure "<>show a, "") []
   x <*> y = ViewGrammar $ Tree.Node ("<*>", "") [unViewGrammar x, unViewGrammar y]
   x <* y = ViewGrammar $ Tree.Node ("<*", "") [unViewGrammar x, unViewGrammar y]
   x *> y = ViewGrammar $ Tree.Node ("*>", "") [unViewGrammar x, unViewGrammar y]
@@ -90,10 +93,9 @@ instance CombMatchable (ViewGrammar sN) where
   conditional a bs d = ViewGrammar $ Tree.Node ("conditional", "")
     $ Tree.Node ("condition", "") [unViewGrammar a]
     : Tree.Node ("default", "") [unViewGrammar d]
-    : ((\(p,b) -> Tree.Node ("branch "<>showProduction p, "") [unViewGrammar b]) Functor.<$> bs)
+    : ((\(p,b) -> Tree.Node ("branch "<>show p, "") [unViewGrammar b]) Functor.<$> bs)
 instance CombSatisfiable tok (ViewGrammar sN) where
-  satisfyOrFail _fs p = ViewGrammar $ Tree.Node
-    ("satisfy "<>showProduction p, "") []
+  satisfyOrFail p = ViewGrammar $ Tree.Node ("satisfy "<>show p, "") []
 instance CombSelectable (ViewGrammar sN) where
   branch lr l r = ViewGrammar $ Tree.Node ("branch", "")
     [ unViewGrammar lr, unViewGrammar l, unViewGrammar r ]
@@ -101,3 +103,8 @@ instance CombRegisterableUnscoped (ViewGrammar sN) where
   newUnscoped r x y = ViewGrammar $ Tree.Node ("new "<>show r, "") [ unViewGrammar x,  unViewGrammar y ]
   getUnscoped r = ViewGrammar $ Tree.Node ("get "<>show r, "") [ ]
   putUnscoped r x = ViewGrammar $ Tree.Node ("put "<>show r, "") [ unViewGrammar x ]
+instance CombRegisterable (ViewGrammar sN) where
+  new x f = undefined
+  get = undefined
+  put = undefined
+  -- FIXME
diff --git a/src/Symantic/Parser/Grammar/Write.hs b/src/Symantic/Parser/Grammar/Write.hs
index 44c6b78..9e8bdc0 100644
--- a/src/Symantic/Parser/Grammar/Write.hs
+++ b/src/Symantic/Parser/Grammar/Write.hs
@@ -1,9 +1,10 @@
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE DeriveLift #-}
 module Symantic.Parser.Grammar.Write where
 
 import Control.Monad (Monad(..))
 import Data.Bool (Bool(..))
-import Data.Function (($))
+import Data.Function (($), (.))
 import Data.Maybe (Maybe(..), fromMaybe, catMaybes)
 import Data.Monoid (Monoid(..))
 import Data.Semigroup (Semigroup(..))
@@ -15,163 +16,160 @@ import qualified Data.HashMap.Strict as HM
 import qualified Data.List as List
 import qualified Data.Text.Lazy as TL
 import qualified Data.Text.Lazy.Builder as TLB
+import Control.DeepSeq (NFData(..))
+import qualified Language.Haskell.TH as TH
+import qualified Language.Haskell.TH.Syntax as TH
+import Prelude (undefined)
+import Debug.Trace
 
 import Symantic.Semantics.SharingObserver
 import Symantic.Semantics.Viewer.Fixity
 import Symantic.Parser.Grammar.Combinators
+import Symantic.Parser.Grammar.SharingObserver
 
 -- * Type 'WriteGrammar'
 newtype WriteGrammar (showName::Bool) a = WriteGrammar { unWriteGrammar ::
-  WriteGrammarInh -> Maybe TLB.Builder }
+  WriteGrammarEnv -> Maybe TLB.Builder }
+  deriving (NFData)
 
 instance IsString (WriteGrammar sN a) where
-  fromString s = WriteGrammar $ \_inh ->
+  fromString s = WriteGrammar $ \_env ->
     if List.null s then Nothing
     else Just (fromString s)
 
--- ** Type 'WriteGrammarInh'
-data WriteGrammarInh
- =   WriteGrammarInh
- {   writeGrammarInh_indent :: TLB.Builder
- ,   writeGrammarInh_op :: (Infix, Side)
- ,   writeGrammarInh_pair :: Pair
- }
-
-emptyWriteGrammarInh :: WriteGrammarInh
-emptyWriteGrammarInh = WriteGrammarInh
- { writeGrammarInh_indent = "\n"
- , writeGrammarInh_op = (infixN0, SideL)
- , writeGrammarInh_pair = pairParen
- }
+-- ** Type 'WriteGrammarEnv'
+data WriteGrammarEnv
+ =   WriteGrammarEnv
+ {   writeGrammarEnvIndent :: TLB.Builder
+ ,   writeGrammarEnvOpFixity :: Infix
+ ,   writeGrammarEnvOpSide :: Side
+ ,   writeGrammarEnvPair :: Pair
+ } deriving (Show)
 
 writeGrammar :: WriteGrammar sN a -> TL.Text
 writeGrammar (WriteGrammar go) =
   TLB.toLazyText $ fromMaybe "" $
-  go emptyWriteGrammarInh
+  go WriteGrammarEnv
+    { writeGrammarEnvIndent = "\n"
+    , writeGrammarEnvOpFixity = infixN0
+    , writeGrammarEnvOpSide = SideL
+    , writeGrammarEnvPair = pairParen
+    }
+
+instance Show (WriteGrammar sN a) where
+  show = TL.unpack . writeGrammar
 
-pairWriteGrammarInh ::
- Semigroup s => IsString s =>
- WriteGrammarInh -> Infix -> Maybe s -> Maybe s
-pairWriteGrammarInh inh op s =
-  if isPairNeeded (writeGrammarInh_op inh) op
-  then Just (fromString o<>" ")<>s<>Just (" "<>fromString c)
-  else s
-  where (o,c) = writeGrammarInh_pair inh
+writeGrammarPair ::
+  Infix -> (WriteGrammarEnv -> Maybe TLB.Builder) -> WriteGrammar sN a
+writeGrammarPair op wg = WriteGrammar $ \env ->
+  let newEnv = env{writeGrammarEnvOpFixity=op, writeGrammarEnvOpSide=SideL} in
+  if isPairNeeded (writeGrammarEnvOpFixity env, writeGrammarEnvOpSide env) op
+  then
+    let (o,c) = writeGrammarEnvPair env in
+    Just (fromString o)<> wg newEnv <> Just (fromString c)
+  else wg newEnv
 
 instance CombAlternable (WriteGrammar sN) where
-  alt exn x y = WriteGrammar $ \inh ->
-    pairWriteGrammarInh inh op $
-    unWriteGrammar x inh
-     { writeGrammarInh_op = (op, SideL)
-     , writeGrammarInh_pair = pairParen
+  alt exn x y = writeGrammarPair (infixB SideL 3) $ \env ->
+    unWriteGrammar x env
+     { writeGrammarEnvOpSide = SideL
+     , writeGrammarEnvPair = pairParen
      } <>
     Just (" |^"<>fromString (show exn)<>" ") <>
-    unWriteGrammar y inh
-     { writeGrammarInh_op = (op, SideR)
-     , writeGrammarInh_pair = pairParen
+    unWriteGrammar y env
+     { writeGrammarEnvOpSide = SideR
+     , writeGrammarEnvPair = pairParen
      }
-    where op = infixB SideL 3
-  throw exn = WriteGrammar $ \inh ->
-    pairWriteGrammarInh inh op $
-      Just ("throw "<>fromString (show exn))
-    where
-    op = infixN 9
-  failure _sf = "failure"
+  throw exn = writeGrammarPair (infixN 9) $ \env ->
+    Just ("throw "<>fromString (show exn))
   empty = "empty"
-  try x = WriteGrammar $ \inh ->
-    pairWriteGrammarInh inh op $
-      Just "try " <> unWriteGrammar x inh
-    where
-    op = infixN 9
+  try x = writeGrammarPair (infixN 9) $ \env ->
+    Just "try " <> unWriteGrammar x env
 instance CombApplicable (WriteGrammar sN) where
   pure _ = WriteGrammar $ return Nothing{-TODO: print?-}
   -- pure _ = "pure"
-  WriteGrammar x <*> WriteGrammar y = WriteGrammar $ \inh ->
-    let inh' side = inh
-         { writeGrammarInh_op = (op, side)
-         , writeGrammarInh_pair = pairParen
-         } in
-    case x (inh' SideL) of
-     Nothing -> y (inh' SideR)
-     Just xt ->
-      case y (inh' SideR) of
-       Nothing -> Just xt
-       Just yt ->
-        pairWriteGrammarInh inh op $
-          Just $ xt <> ", " <> yt
-    where
-    op = infixN 1
+  x <*> y = writeGrammarPair (infixB SideL 4) $ \env ->
+    let env' side = env { writeGrammarEnvPair = pairParen } in
+    case unWriteGrammar x (env' SideL) of
+      Nothing -> unWriteGrammar y (env' SideR)
+      Just xText ->
+       case unWriteGrammar y (env' SideR) of
+         Nothing -> Just xText
+         Just _yText ->
+           unWriteGrammar x env{writeGrammarEnvOpSide = SideL} <>
+           Just " " <>
+           unWriteGrammar y env{writeGrammarEnvOpSide = SideR}
 instance CombFoldable (WriteGrammar sN) where
-  chainPre f x = WriteGrammar $ \inh ->
-    pairWriteGrammarInh inh op $
-      Just "chainPre " <>
-      unWriteGrammar f inh <> Just " " <>
-      unWriteGrammar x inh
-    where op = infixN 9
-  chainPost f x = WriteGrammar $ \inh ->
-    pairWriteGrammarInh inh op $
-      Just "chainPost " <>
-      unWriteGrammar f inh <> Just " " <>
-      unWriteGrammar x inh
-    where op = infixN 9
+  chainPre f x = writeGrammarPair (infixN 9) $ \env ->
+    Just "chainPre " <>
+    unWriteGrammar f env <> Just " " <>
+    unWriteGrammar x env
+  chainPost f x = writeGrammarPair (infixN 9) $ \env ->
+    Just "chainPost " <>
+    unWriteGrammar f env <> Just " " <>
+    unWriteGrammar x env
 instance
   ( Show letName
   , HideName letName
   , HideableName sN
   ) => Referenceable letName (WriteGrammar sN) where
-  ref isRec name = WriteGrammar $ \inh ->
-    pairWriteGrammarInh inh op $
-      Just (if isRec then "rec " else "ref ") <>
-      Just (fromString (show (hideableName @sN name)))
-    where
-    op = infixN 9
+  ref isRec name = writeGrammarPair (infixN 9) $ \env ->
+    Just (if isRec then "rec " else "ref ") <>
+    Just (fromString (show (hideableName @sN name)))
 instance
   ( Show letName
   , HideName letName
   , HideableName sN
   ) => Letsable letName (WriteGrammar sN) where
-  lets defs x = WriteGrammar $ \inh ->
-    pairWriteGrammarInh inh op $
-      Just "let "
-      <> HM.foldMapWithKey
-        (\name (SomeLet val) ->
-          Just (fromString (show (hideableName @sN name)))
-          <> unWriteGrammar val inh)
-        defs
-      <> unWriteGrammar x inh
-    where
-    op = infixN 9
+  lets defs x = writeGrammarPair (infixN 9) $ \env ->
+    Just "let "
+    <> HM.foldMapWithKey
+      (\name (SomeLet val) ->
+        Just (fromString (show (hideableName @sN name)))
+        <> unWriteGrammar val env)
+      defs
+    <> unWriteGrammar x env
 instance CombLookable (WriteGrammar sN) where
-  look x = WriteGrammar $ \inh ->
-    pairWriteGrammarInh inh op $
-      Just "look " <> unWriteGrammar x inh
-    where op = infixN 9
-  negLook x = WriteGrammar $ \inh ->
-    pairWriteGrammarInh inh op $
-      Just "negLook " <> unWriteGrammar x inh
-    where op = infixN 9
+  look x = writeGrammarPair (infixN 9) $ \env ->
+    Just "look " <> unWriteGrammar x env
+  negLook x = writeGrammarPair (infixN 9) $ \env ->
+    Just "negLook " <> unWriteGrammar x env
   eof = "eof"
 instance CombMatchable (WriteGrammar sN) where
-  conditional a bs d = WriteGrammar $ \inh ->
-    pairWriteGrammarInh inh op $
-      Just "conditional " <>
-      unWriteGrammar a inh <>
-      unWriteGrammar d inh <>
-      Just " [" <>
-      Just (mconcat (List.intersperse ", " $
-      catMaybes $ (Functor.<$> bs) $ \(p{-TODO: print?-}, b) ->
-        unWriteGrammar b inh{writeGrammarInh_op=(infixN 0, SideL)})) <>
-      Just "] "
-    where
-    op = infixN 9
+  conditional a bs d = writeGrammarPair (infixN 9) $ \env ->
+    Just "conditional " <>
+    unWriteGrammar a env <>
+    unWriteGrammar d env <>
+    Just " [" <>
+    Just (mconcat (List.intersperse ", " $
+    catMaybes $ (Functor.<$> bs) $ \(p{-TODO: print?-}, b) ->
+      unWriteGrammar b env
+        { writeGrammarEnvOpFixity = infixN 0
+        , writeGrammarEnvOpSide = SideL
+        })) <>
+    Just "] "
 instance CombSatisfiable tok (WriteGrammar sN) where
-  satisfyOrFail _fs _f = "satisfy"
+  satisfyOrFail p = writeGrammarPair (infixN 9) $ \env ->
+    Just "satisfy " <>
+    Just (fromString (showsPrec 10 p ""))
 instance CombSelectable (WriteGrammar sN) where
-  branch lr l r = WriteGrammar $ \inh ->
-    pairWriteGrammarInh inh op $
-      Just "branch " <>
-      unWriteGrammar lr inh <> Just " " <>
-      unWriteGrammar l inh <> Just " " <>
-      unWriteGrammar r inh
-    where
-    op = infixN 9
+  branch lr l r = writeGrammarPair (infixN 9) $ \env ->
+    Just "branch " <>
+    unWriteGrammar lr env <> Just " " <>
+    unWriteGrammar l env <> Just " " <>
+    unWriteGrammar r env
+instance CombRegisterableUnscoped (WriteGrammar sN) where
+  newUnscoped r x y = writeGrammarPair (infixN 9) $ \env ->
+    Just "newUnscoped " <> Just (fromString (show r)) <>
+    unWriteGrammar x env <> Just " " <>
+    unWriteGrammar y env
+  getUnscoped r = writeGrammarPair (infixN 9) $ \env ->
+    Just "getUnscoped " <> Just (fromString (show r))
+  putUnscoped r x = writeGrammarPair (infixN 9) $ \env ->
+    Just "putUnscoped " <> Just (fromString (show r)) <>
+    unWriteGrammar x env
+instance CombRegisterable (WriteGrammar sN) where
+  new x f = undefined
+  get = undefined
+  put = undefined
+  -- FIXME
diff --git a/src/Symantic/Parser/Machine/View.hs b/src/Symantic/Parser/Machine/View.hs
index b0cd26b..d305735 100644
--- a/src/Symantic/Parser/Machine/View.hs
+++ b/src/Symantic/Parser/Machine/View.hs
@@ -127,7 +127,7 @@ instance
     } where gen = raise exn
   fail fs = ViewMachine
     { unViewMachine = \lm next ->
-        viewInstrCmd @sN (Right gen) lm ("fail "<>show (Set.toList fs), "") [] : next
+        viewInstrCmd @sN (Right gen) lm ("fail "{-<>show fs-}, "") [] : next
     , viewGen = gen
     } where gen = fail fs
   commit exn k = ViewMachine
@@ -229,23 +229,23 @@ instance
   ( HideableName sN
   , InstrReadable tok Gen
   ) => InstrReadable tok (ViewMachine sN) where
-  read es p k = ViewMachine
+  read p k = ViewMachine
     { unViewMachine = \lm next ->
         viewInstrCmd @sN (Right gen) lm ("read "<>showSplice p, "") [] :
         unViewMachine k lm next
     , viewGen = gen
-    } where gen = read es p (viewGen k)
+    } where gen = read p (viewGen k)
 instance
   HideableName sN =>
   InstrIterable (ViewMachine sN) where
-  iter jumpName@(LetName n) ok ko = ViewMachine
+  iter jumpName@(LetName n) loop done = ViewMachine
     { unViewMachine = \lm next ->
         viewInstrCmd @sN (Right gen) lm ("iter", " "<>show (hideableName @sN n))
-          [ viewInstrArg "ok" (unViewMachine ok lm [])
-          , viewInstrArg "ko" (unViewMachine ko lm [])
+          [ viewInstrArg "loop" (unViewMachine loop lm [])
+          , viewInstrArg "done" (unViewMachine done lm [])
           ] : next
     , viewGen = gen
-    } where gen = iter jumpName (viewGen ok) (viewGen ko)
+    } where gen = iter jumpName (viewGen loop) (viewGen done)
 instance
   HideableName sN =>
   InstrRegisterable (ViewMachine sN) where
-- 
2.47.2