html
This commit is contained in:
@@ -35,10 +35,10 @@ library
|
|||||||
, Rlp.AltSyntax
|
, Rlp.AltSyntax
|
||||||
, Rlp.AltParse
|
, Rlp.AltParse
|
||||||
, Rlp.HindleyMilner
|
, Rlp.HindleyMilner
|
||||||
|
, Rlp.HindleyMilner.Visual
|
||||||
, Rlp.HindleyMilner.Types
|
, Rlp.HindleyMilner.Types
|
||||||
, Rlp.Syntax.Backstage
|
, Rlp.Syntax.Backstage
|
||||||
, Rlp.Syntax.Types
|
, Rlp.Syntax.Types
|
||||||
, Rlp.Syntax.Good
|
|
||||||
-- , Rlp.Parse.Decls
|
-- , Rlp.Parse.Decls
|
||||||
, Rlp.Parse
|
, Rlp.Parse
|
||||||
, Rlp.Parse.Associate
|
, Rlp.Parse.Associate
|
||||||
@@ -56,6 +56,7 @@ library
|
|||||||
, Control.Monad.Utils
|
, Control.Monad.Utils
|
||||||
, Misc
|
, Misc
|
||||||
, Misc.Lift1
|
, Misc.Lift1
|
||||||
|
, Misc.CofreeF
|
||||||
, Core.SystemF
|
, Core.SystemF
|
||||||
|
|
||||||
build-tool-depends: happy:happy, alex:alex
|
build-tool-depends: happy:happy, alex:alex
|
||||||
@@ -87,6 +88,11 @@ library
|
|||||||
, these >=0.2 && <2.0
|
, these >=0.2 && <2.0
|
||||||
, free >=5.2
|
, free >=5.2
|
||||||
, bifunctors >=5.2
|
, bifunctors >=5.2
|
||||||
|
, blaze-html
|
||||||
|
, blaze-markup
|
||||||
|
, clay
|
||||||
|
, jmacro
|
||||||
|
, js-jquery
|
||||||
|
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
default-language: GHC2021
|
default-language: GHC2021
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ import Language.Haskell.TH.Syntax (Lift)
|
|||||||
|
|
||||||
import Control.Comonad
|
import Control.Comonad
|
||||||
import Control.Comonad.Cofree
|
import Control.Comonad.Cofree
|
||||||
import Control.Comonad.Trans.Cofree qualified as Trans.Cofree
|
|
||||||
import Control.Comonad.Trans.Cofree (CofreeF)
|
|
||||||
import Data.Functor.Apply
|
import Data.Functor.Apply
|
||||||
import Data.Functor.Bind
|
import Data.Functor.Bind
|
||||||
import Data.Functor.Compose
|
import Data.Functor.Compose
|
||||||
@@ -40,15 +38,13 @@ import Control.Lens hiding ((<<~), (:<))
|
|||||||
|
|
||||||
import Data.List.NonEmpty (NonEmpty)
|
import Data.List.NonEmpty (NonEmpty)
|
||||||
import Data.Function (on)
|
import Data.Function (on)
|
||||||
|
import Misc.CofreeF
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Token wrapped with a span (line, column, absolute, length)
|
-- | Token wrapped with a span (line, column, absolute, length)
|
||||||
data Located a = Located SrcSpan a
|
data Located a = Located SrcSpan a
|
||||||
deriving (Show, Lift, Functor)
|
deriving (Show, Lift, Functor)
|
||||||
|
|
||||||
pattern (:<$) :: a -> f b -> Trans.Cofree.CofreeF f a b
|
|
||||||
pattern a :<$ b = a Trans.Cofree.:< b
|
|
||||||
|
|
||||||
(<~>) :: a -> b -> SrcSpan
|
(<~>) :: a -> b -> SrcSpan
|
||||||
(<~>) = undefined
|
(<~>) = undefined
|
||||||
|
|
||||||
|
|||||||
@@ -720,7 +720,7 @@ class HasArrowStops s t a b | s -> a, t -> b, s b -> t, t a -> s where
|
|||||||
|
|
||||||
instance HasArrowStops Type Type Type Type where
|
instance HasArrowStops Type Type Type Type where
|
||||||
arrowStops k (s :-> t) = (:->) <$> k s <*> arrowStops k t
|
arrowStops k (s :-> t) = (:->) <$> k s <*> arrowStops k t
|
||||||
arrowStops k t = k t
|
arrowStops k t = k t
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ class Pretty a where
|
|||||||
rpretty :: (IsString s, Pretty a) => a -> s
|
rpretty :: (IsString s, Pretty a) => a -> s
|
||||||
rpretty = fromString . render . pretty
|
rpretty = fromString . render . pretty
|
||||||
|
|
||||||
|
instance Pretty Doc where
|
||||||
|
pretty = id
|
||||||
|
|
||||||
instance Pretty String where
|
instance Pretty String where
|
||||||
pretty = Text.PrettyPrint.text
|
pretty = Text.PrettyPrint.text
|
||||||
|
|
||||||
@@ -71,9 +74,6 @@ instance (Pretty1 f, Pretty1 g) => Pretty1 (Sum f g) where
|
|||||||
instance (Pretty (f (Fix f))) => Pretty (Fix f) where
|
instance (Pretty (f (Fix f))) => Pretty (Fix f) where
|
||||||
prettyPrec d (Fix f) = prettyPrec d f
|
prettyPrec d (Fix f) = prettyPrec d f
|
||||||
|
|
||||||
-- instance (Pretty1 f) => Pretty (Fix f) where
|
|
||||||
-- prettyPrec d (Fix f) = prettyPrec1 d f
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
ttext :: Pretty t => t -> Doc
|
ttext :: Pretty t => t -> Doc
|
||||||
|
|||||||
13
src/Misc/CofreeF.hs
Normal file
13
src/Misc/CofreeF.hs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{-# LANGUAGE PatternSynonyms #-}
|
||||||
|
module Misc.CofreeF
|
||||||
|
( pattern (:<$)
|
||||||
|
)
|
||||||
|
where
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
import Control.Comonad.Trans.Cofree qualified as Trans.Cofree
|
||||||
|
import Control.Comonad.Trans.Cofree (CofreeF)
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
pattern (:<$) :: a -> f b -> Trans.Cofree.CofreeF f a b
|
||||||
|
pattern a :<$ b = a Trans.Cofree.:< b
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ programDecls = lens (\ (Program ds) -> ds) (const Program)
|
|||||||
data Decl b a = FunD b [Pat b] a
|
data Decl b a = FunD b [Pat b] a
|
||||||
| DataD b [b] [DataCon b]
|
| DataD b [b] [DataCon b]
|
||||||
| TySigD b (Type b)
|
| TySigD b (Type b)
|
||||||
deriving Show
|
deriving (Show, Functor)
|
||||||
|
|
||||||
data DataCon b = DataCon b [Type b]
|
data DataCon b = DataCon b [Type b]
|
||||||
deriving (Show, Generic)
|
deriving (Show, Generic)
|
||||||
@@ -217,3 +217,7 @@ instance (Hashable b) => Hashable1 (ExprF b)
|
|||||||
|
|
||||||
makeBaseFunctor ''Type
|
makeBaseFunctor ''Type
|
||||||
|
|
||||||
|
instance Core.HasArrowStops (Type b) (Type b) (Type b) (Type b) where
|
||||||
|
arrowStops k (s Core.:-> t) = (Core.:->) <$> k s <*> Core.arrowStops k t
|
||||||
|
arrowStops k t = k t
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
module Rlp.HindleyMilner
|
module Rlp.HindleyMilner
|
||||||
( typeCheckRlpProgR
|
( typeCheckRlpProgR
|
||||||
, solve
|
, solve
|
||||||
|
, annotate
|
||||||
, TypeError(..)
|
, TypeError(..)
|
||||||
, runHM'
|
, runHM'
|
||||||
, HM
|
, HM
|
||||||
@@ -11,6 +12,7 @@ module Rlp.HindleyMilner
|
|||||||
where
|
where
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
import Control.Lens hiding (Context', Context, (:<), para)
|
import Control.Lens hiding (Context', Context, (:<), para)
|
||||||
|
import Control.Lens.Unsound
|
||||||
import Control.Monad.Errorful
|
import Control.Monad.Errorful
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
import Control.Monad.Accum
|
import Control.Monad.Accum
|
||||||
@@ -77,14 +79,27 @@ gather' = \case
|
|||||||
let jtfx = mempty & constraints .~ [Equality tf (tx :-> tfx)]
|
let jtfx = mempty & constraints .~ [Equality tf (tx :-> tfx)]
|
||||||
pure (tfx, jf <> jx <> jtfx)
|
pure (tfx, jf <> jx <> jtfx)
|
||||||
|
|
||||||
Finl (LamF [b] e) -> do
|
Finl (LamF bs e) -> do
|
||||||
tb <- freshTv
|
tbs <- for bs (const freshTv)
|
||||||
(te,je) <- gather e
|
(te,je) <- gather e
|
||||||
let cs = maybe [] (fmap $ Equality tb) (je ^. assumptions . at b)
|
let cs = concatMap (uncurry . equals $ je ^. assumptions) $ bs `zip` tbs
|
||||||
as = je ^. assumptions & at b .~ Nothing
|
as = foldr H.delete (je ^. assumptions) bs
|
||||||
j = mempty & constraints .~ cs & assumptions .~ as
|
j = mempty & constraints .~ cs & assumptions .~ as
|
||||||
t = tb :-> te
|
t = foldr (:->) te tbs
|
||||||
pure (t,j)
|
pure (t,j)
|
||||||
|
where
|
||||||
|
equals as b tb = maybe []
|
||||||
|
(fmap $ Equality tb)
|
||||||
|
(as ^. at b)
|
||||||
|
|
||||||
|
-- Finl (LamF [b] e) -> do
|
||||||
|
-- tb <- freshTv
|
||||||
|
-- (te,je) <- gather e
|
||||||
|
-- let cs = maybe [] (fmap $ Equality tb) (je ^. assumptions . at b)
|
||||||
|
-- as = je ^. assumptions & at b .~ Nothing
|
||||||
|
-- j = mempty & constraints .~ cs & assumptions .~ as
|
||||||
|
-- t = tb :-> te
|
||||||
|
-- pure (t,j)
|
||||||
|
|
||||||
unify :: [Constraint] -> HM Context
|
unify :: [Constraint] -> HM Context
|
||||||
|
|
||||||
@@ -122,11 +137,8 @@ infer1 e = do
|
|||||||
g <- unify (j ^. constraints)
|
g <- unify (j ^. constraints)
|
||||||
pure $ ifoldrOf (contextVars . itraversed) subst t g
|
pure $ ifoldrOf (contextVars . itraversed) subst t g
|
||||||
|
|
||||||
solve = undefined
|
solve :: RlpExpr PsName -> HM (Cofree (RlpExprF PsName) (Type PsName))
|
||||||
-- solve g e = do
|
solve e = sequenceA $ fixtend (infer1 . wrapFix) e
|
||||||
-- (t,j) <- gather e
|
|
||||||
-- g' <- unify cs
|
|
||||||
-- pure $ ifoldrOf (contextVars . itraversed) subst t g'
|
|
||||||
|
|
||||||
occurs :: PsName -> Type PsName -> Bool
|
occurs :: PsName -> Type PsName -> Bool
|
||||||
occurs n = cata \case
|
occurs n = cata \case
|
||||||
|
|||||||
133
src/Rlp/HindleyMilner/Visual.hs
Normal file
133
src/Rlp/HindleyMilner/Visual.hs
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
{-# LANGUAGE LexicalNegation #-}
|
||||||
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
module Rlp.HindleyMilner.Visual
|
||||||
|
(
|
||||||
|
)
|
||||||
|
where
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
import Control.Monad
|
||||||
|
import System.IO
|
||||||
|
import Data.Text qualified as T
|
||||||
|
import Data.Text.IO qualified as T
|
||||||
|
import Data.Pretty
|
||||||
|
import Data.String (IsString(..))
|
||||||
|
import Data.Foldable
|
||||||
|
import Misc.CofreeF
|
||||||
|
import Control.Exception
|
||||||
|
|
||||||
|
import Data.Functor.Foldable
|
||||||
|
|
||||||
|
import Text.Blaze.Html5 as H
|
||||||
|
import Text.Blaze.Html5.Attributes as A
|
||||||
|
import Text.Blaze.Html.Renderer.String
|
||||||
|
import Clay (Css, (?), px, pct, (**), (|>), (|+)
|
||||||
|
, (|~))
|
||||||
|
import Clay qualified as C
|
||||||
|
import Clay.Render qualified as C
|
||||||
|
import Language.Javascript.JMacro
|
||||||
|
import Language.Javascript.JQuery qualified as JQuery
|
||||||
|
|
||||||
|
import Core.Syntax as Core
|
||||||
|
import Rlp.AltSyntax as Rlp
|
||||||
|
import Rlp.HindleyMilner
|
||||||
|
|
||||||
|
import Prelude hiding ((**))
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type AnnExpr = Cofree (RlpExprF PsName)
|
||||||
|
|
||||||
|
tooltips :: Css
|
||||||
|
tooltips = do
|
||||||
|
".has-type" ? do
|
||||||
|
C.position C.relative
|
||||||
|
C.display C.inlineBlock
|
||||||
|
C.borderBottom (px 1) C.dotted C.black
|
||||||
|
".has-type.hovering" ? do
|
||||||
|
C.background C.green
|
||||||
|
".has-type.hovering" |> ".type-text" ? do
|
||||||
|
C.display C.block
|
||||||
|
C.opacity 1
|
||||||
|
C.position C.fixed
|
||||||
|
C.overflowWrap C.breakWord
|
||||||
|
".has-type" |> ".type-text" ? do
|
||||||
|
C.display C.none
|
||||||
|
C.overflowWrap C.breakWord
|
||||||
|
C.maxWidth (pct 50)
|
||||||
|
|
||||||
|
stylesheet :: Css
|
||||||
|
stylesheet = tooltips
|
||||||
|
|
||||||
|
numbers :: Int -> Html
|
||||||
|
numbers n = docTypeHtml do
|
||||||
|
H.head do
|
||||||
|
H.title "naturals"
|
||||||
|
H.style "doge"
|
||||||
|
body do
|
||||||
|
pre "a list of nats"
|
||||||
|
ul $ forM_ [1..n] (li . toHtml)
|
||||||
|
|
||||||
|
withTooltip :: Html -> Html -> Html
|
||||||
|
withTooltip normal hover =
|
||||||
|
H.div ! class_ "has-type"
|
||||||
|
$ normal *> (H.div ! class_ "type-text" $ hover)
|
||||||
|
|
||||||
|
-- withTooltip :: Html -> Html -> Html
|
||||||
|
-- withTooltip normal hover =
|
||||||
|
-- H.div ! class_ "has-type"
|
||||||
|
-- -- ! onload "installHoverListener(this)"
|
||||||
|
-- $ normal
|
||||||
|
|
||||||
|
annExpr :: (ann -> Doc) -> AnnExpr ann -> Html
|
||||||
|
annExpr sf = code . cata \case
|
||||||
|
t :<$ InL (LitF l) -> withTooltip (rpretty l) (sf' t)
|
||||||
|
t :<$ InL (VarF n) -> withTooltip (rpretty n) (sf' t)
|
||||||
|
t :<$ InL (AppF f x) -> withTooltip (f *> " " *> x) (sf' t)
|
||||||
|
t :<$ InL (LamF bs e) -> withTooltip ("λ" *> bs' *> " -> " *> e) (sf' t)
|
||||||
|
where
|
||||||
|
bs' = fromString . render . hsep $ prettyPrec appPrec1 <$> bs
|
||||||
|
where
|
||||||
|
sf' = fromString . show . sf
|
||||||
|
|
||||||
|
rootScript :: JStat
|
||||||
|
rootScript = [jmacro|
|
||||||
|
$(".has-type").on("mouseover mouseout", \e {
|
||||||
|
e.stopPropagation();
|
||||||
|
$(this).toggleClass("hovering", e.type === "mouseover");
|
||||||
|
var o = $(this).children(".type-text")[0];
|
||||||
|
var x = e.clientX;
|
||||||
|
var y = e.clientY;
|
||||||
|
o.style.top = (y + 20) + 'px';
|
||||||
|
o.style.left = (x + 20) + 'px';
|
||||||
|
});
|
||||||
|
|]
|
||||||
|
|
||||||
|
jsScript :: (IsString s, JsToDoc w, JMacro w) => w -> s
|
||||||
|
jsScript = fromString . show . renderJs
|
||||||
|
|
||||||
|
rootPage :: Html -> Html
|
||||||
|
rootPage html = docTypeHtml do
|
||||||
|
H.head do
|
||||||
|
H.title "naturals"
|
||||||
|
H.style (toHtml . C.render $ stylesheet)
|
||||||
|
H.body do
|
||||||
|
html
|
||||||
|
script ! src (fromString $ "https:" ++ JQuery.url) $ ""
|
||||||
|
script ! src "https://code.jquery.com/ui/1.13.2/jquery-ui.min.js" $ ""
|
||||||
|
script (fromString . show . renderJs $ rootScript)
|
||||||
|
|
||||||
|
renderTmp :: Html -> IO ()
|
||||||
|
renderTmp = writeFile "/tmp/t.html" . renderHtml
|
||||||
|
|
||||||
|
renderTmp' :: Html -> IO ()
|
||||||
|
renderTmp' = writeFile "/tmp/t.html" . renderHtml . rootPage
|
||||||
|
|
||||||
|
renderExpr :: RlpExpr PsName -> IO ()
|
||||||
|
renderExpr e = case runHM' . annotate $ e of
|
||||||
|
Left es -> error (show es)
|
||||||
|
Right e' -> renderTmp' . annExpr (fromString . show) $ e'
|
||||||
|
|
||||||
|
renderExpr' :: RlpExpr PsName -> IO ()
|
||||||
|
renderExpr' e = case runHM' . solve $ e of
|
||||||
|
Left es -> error (show es)
|
||||||
|
Right e' -> renderTmp' . annExpr pretty $ e'
|
||||||
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
{-# LANGUAGE TemplateHaskell #-}
|
|
||||||
module Rlp.Syntax.Good
|
|
||||||
( Decl(..), Program(..)
|
|
||||||
, programDecls
|
|
||||||
, Mistake(..)
|
|
||||||
)
|
|
||||||
where
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
import Data.Kind
|
|
||||||
import Control.Lens
|
|
||||||
import Rlp.Syntax.Types (NameP)
|
|
||||||
import Rlp.Syntax.Types qualified as Rlp
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
data Program b a = Program
|
|
||||||
{ _programDecls :: [Decl b a]
|
|
||||||
}
|
|
||||||
|
|
||||||
data Decl p a = FunD (NameP p) [Rlp.Pat p] a
|
|
||||||
| TySigD [NameP p] (Rlp.Ty p)
|
|
||||||
| DataD (NameP p) [NameP p] [Rlp.ConAlt p]
|
|
||||||
| InfixD Rlp.Assoc Int (NameP p)
|
|
||||||
|
|
||||||
type Where p a = [Binding p a]
|
|
||||||
|
|
||||||
data Binding p a = PatB (Rlp.Pat p) a
|
|
||||||
deriving (Functor, Foldable, Traversable)
|
|
||||||
|
|
||||||
makeLenses ''Program
|
|
||||||
|
|
||||||
class Mistake a where
|
|
||||||
type family Ammend a :: Type
|
|
||||||
ammendMistake :: a -> Ammend a
|
|
||||||
|
|
||||||
instance Mistake (Rlp.Program p a) where
|
|
||||||
type Ammend (Rlp.Program p a) = Program p (Rlp.Expr' p a)
|
|
||||||
|
|
||||||
ammendMistake p = Program
|
|
||||||
{ _programDecls = ammendMistake <$> Rlp._programDecls p
|
|
||||||
}
|
|
||||||
|
|
||||||
instance Mistake (Rlp.Decl p a) where
|
|
||||||
type Ammend (Rlp.Decl p a) = Decl p (Rlp.Expr' p a)
|
|
||||||
|
|
||||||
ammendMistake = \case
|
|
||||||
Rlp.FunD n as e _ -> FunD n as e
|
|
||||||
Rlp.TySigD ns t -> TySigD ns t
|
|
||||||
Rlp.DataD n as cs -> DataD n as cs
|
|
||||||
Rlp.InfixD ass p n -> InfixD ass p n
|
|
||||||
|
|
||||||
instance Mistake (Rlp.Binding p a) where
|
|
||||||
type Ammend (Rlp.Binding p a) = Binding p (Rlp.ExprF p a)
|
|
||||||
|
|
||||||
ammendMistake = \case
|
|
||||||
Rlp.PatB k v -> PatB k v
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user