2023-11-26 11:43:38 -08:00
|
|
|
module Main exposing (main)
|
|
|
|
|
|
|
|
import Browser
|
|
|
|
import Html exposing (Html)
|
2023-11-30 21:29:37 -08:00
|
|
|
import Html.Events exposing (onInput, onClick)
|
|
|
|
import Html.Attributes exposing (type_, class, classList, value)
|
2023-12-02 00:07:01 -08:00
|
|
|
import Html.Lazy
|
2023-11-26 11:43:38 -08:00
|
|
|
import Bergamot.Syntax exposing (..)
|
|
|
|
import Bergamot.Search exposing (..)
|
|
|
|
import Bergamot.Rules exposing (..)
|
|
|
|
import Bergamot.Parser exposing (..)
|
2023-11-26 14:34:52 -08:00
|
|
|
import Bergamot.Latex exposing (..)
|
2023-11-30 22:44:20 -08:00
|
|
|
import Bergamot.ObjectLanguage exposing (..)
|
2023-11-26 15:54:01 -08:00
|
|
|
import Json.Encode
|
2023-11-26 11:43:38 -08:00
|
|
|
import Maybe
|
|
|
|
import Tuple
|
|
|
|
|
2023-11-30 21:29:37 -08:00
|
|
|
type Tab
|
|
|
|
= Editor
|
|
|
|
| Rendered
|
|
|
|
|
|
|
|
tabEq : Tab -> Tab -> Bool
|
|
|
|
tabEq t1 t2 =
|
|
|
|
case (t1, t2) of
|
|
|
|
(Editor, Editor) -> True
|
|
|
|
(Rendered, Rendered) -> True
|
|
|
|
_ -> False
|
|
|
|
|
2023-12-01 11:31:38 -08:00
|
|
|
type EditMode
|
|
|
|
= Query
|
|
|
|
| Syntax
|
|
|
|
|
|
|
|
modeEq : EditMode -> EditMode -> Bool
|
|
|
|
modeEq m1 m2 =
|
|
|
|
case (m1, m2) of
|
|
|
|
(Query, Query) -> True
|
|
|
|
(Syntax, Syntax) -> True
|
|
|
|
_ -> False
|
|
|
|
|
2023-11-26 12:47:05 -08:00
|
|
|
type alias Model =
|
|
|
|
{ program : String
|
2023-12-02 00:25:23 -08:00
|
|
|
, renderProgram: String
|
2023-11-26 12:47:05 -08:00
|
|
|
, query : String
|
2023-12-01 11:31:38 -08:00
|
|
|
, tab : Tab
|
|
|
|
, editMode : EditMode
|
2023-11-26 12:47:05 -08:00
|
|
|
}
|
2023-12-02 00:25:23 -08:00
|
|
|
type alias Flags = { renderRules: String, rules: String, query: String }
|
2023-11-26 11:58:20 -08:00
|
|
|
type Msg
|
|
|
|
= SetProgram String
|
2023-11-26 12:47:05 -08:00
|
|
|
| SetQuery String
|
2023-11-30 21:29:37 -08:00
|
|
|
| SetTab Tab
|
2023-12-01 11:31:38 -08:00
|
|
|
| SetEditMode EditMode
|
2023-11-26 11:43:38 -08:00
|
|
|
|
|
|
|
init : Flags -> (Model, Cmd Msg)
|
2023-12-02 00:25:23 -08:00
|
|
|
init fs = ({ program = fs.rules, renderProgram = fs.renderRules, query = fs.query, tab = Editor, editMode = Query }, Cmd.none)
|
2023-11-26 12:47:05 -08:00
|
|
|
|
2023-11-26 16:25:23 -08:00
|
|
|
viewSection : String -> Html Msg -> Html Msg
|
|
|
|
viewSection name content =
|
2023-11-29 22:20:55 -08:00
|
|
|
Html.div [ class "bergamot-section" ] [ Html.em [ class "bergamot-section-heading" ] [ Html.text name ], content ]
|
2023-11-26 14:34:52 -08:00
|
|
|
|
2023-11-30 21:29:37 -08:00
|
|
|
viewTab : Tab -> Html Msg -> Html Msg -> Html Msg
|
|
|
|
viewTab tab editor rendered =
|
|
|
|
case tab of
|
|
|
|
Editor -> editor
|
|
|
|
Rendered -> rendered
|
|
|
|
|
2023-12-01 11:31:38 -08:00
|
|
|
viewSelector : (a -> a -> Bool) -> (a -> Msg) -> a -> List (a, String) -> Html Msg
|
|
|
|
viewSelector eq mkMsg mode modeNames =
|
|
|
|
Html.div [ class "bergamot-selector" ] <|
|
|
|
|
List.map (\(modep, name) ->
|
|
|
|
Html.button
|
|
|
|
[ classList [("active", eq mode modep)]
|
|
|
|
, onClick (mkMsg modep)
|
|
|
|
] [ Html.text name ]) modeNames
|
|
|
|
|
2023-11-30 21:29:37 -08:00
|
|
|
viewTabSelector : Tab -> List (Tab, String) -> Html Msg
|
2023-12-01 11:31:38 -08:00
|
|
|
viewTabSelector = viewSelector tabEq SetTab
|
|
|
|
|
|
|
|
viewEditModeSelector : EditMode -> List (EditMode, String) -> Html Msg
|
|
|
|
viewEditModeSelector = viewSelector modeEq SetEditMode
|
2023-11-30 21:29:37 -08:00
|
|
|
|
2023-12-01 23:31:43 -08:00
|
|
|
viewRule : RuleEnv -> Rule -> Maybe (Html Msg)
|
|
|
|
viewRule env r = renderRuleViaRules env r
|
|
|
|
|> Maybe.map latex
|
2023-11-26 16:25:23 -08:00
|
|
|
|
2023-12-02 00:25:23 -08:00
|
|
|
viewRules : String -> String -> Html Msg
|
|
|
|
viewRules renderProgs progs = viewSection "Rendered Rules" <|
|
2023-11-29 22:20:55 -08:00
|
|
|
Html.div [ class "bergamot-rule-list" ] <|
|
2023-12-02 00:25:23 -08:00
|
|
|
case (run program renderProgs, run program progs) of
|
|
|
|
(Just renderProg, Just prog) -> List.filterMap (viewRule renderProg) prog.rules
|
|
|
|
_ -> []
|
2023-11-26 16:25:23 -08:00
|
|
|
|
2023-12-01 11:31:38 -08:00
|
|
|
proofGoal : EditMode -> String -> Maybe (Term Metavariable)
|
|
|
|
proofGoal mode querys =
|
|
|
|
case mode of
|
|
|
|
Query -> run term querys
|
|
|
|
Syntax -> Maybe.map (\e -> Call "type" [exprToTerm e, Var (MkMetavariable "tau")]) <| run parseExpr querys
|
|
|
|
|
|
|
|
tryProve : EditMode -> String -> String -> Maybe ProofTree
|
|
|
|
tryProve mode progs querys =
|
|
|
|
case (run program progs, proofGoal mode querys) of
|
2023-11-26 13:14:44 -08:00
|
|
|
(Just prog, Just query) -> single prog (prove query |> Bergamot.Rules.andThen reifyProofTree)
|
2023-11-26 12:47:05 -08:00
|
|
|
_ -> Nothing
|
2023-11-26 11:43:38 -08:00
|
|
|
|
2023-12-01 11:31:38 -08:00
|
|
|
viewProofTree : EditMode -> String -> String -> Html Msg
|
|
|
|
viewProofTree mode progs querys = viewSection "Proof Tree" <|
|
2023-11-29 22:20:55 -08:00
|
|
|
Html.div [ class "bergamot-proof-tree" ] <|
|
2023-12-01 11:31:38 -08:00
|
|
|
case tryProve mode progs querys of
|
2023-11-26 16:25:23 -08:00
|
|
|
Just tree -> [ latex (proofTreeToLatex tree) ]
|
|
|
|
Nothing -> []
|
|
|
|
|
|
|
|
|
2023-11-26 11:43:38 -08:00
|
|
|
view : Model -> Html Msg
|
2023-11-29 22:20:55 -08:00
|
|
|
view m = Html.div [ class "bergamot-root" ]
|
2023-11-30 21:29:37 -08:00
|
|
|
[ viewTabSelector m.tab [(Editor, "Rule Editor"), (Rendered, "Rendered Rules")]
|
2023-12-01 11:31:38 -08:00
|
|
|
, viewEditModeSelector m.editMode [(Query, "Query"), (Syntax, "Language Term")]
|
2023-11-30 21:29:37 -08:00
|
|
|
, viewTab m.tab
|
|
|
|
(viewSection "Rules" <| Html.textarea [ onInput SetProgram ] [ Html.text m.program ])
|
2023-12-02 00:25:23 -08:00
|
|
|
(Html.Lazy.lazy2 viewRules m.renderProgram m.program)
|
2023-11-26 17:17:10 -08:00
|
|
|
, viewSection "Query" <| Html.input [ type_ "text", onInput SetQuery, value m.query ] []
|
2023-12-01 11:31:38 -08:00
|
|
|
, viewProofTree m.editMode m.program m.query
|
2023-11-26 11:58:20 -08:00
|
|
|
]
|
2023-11-26 11:43:38 -08:00
|
|
|
|
|
|
|
update : Msg -> Model -> (Model, Cmd Msg)
|
|
|
|
update msg m =
|
|
|
|
case msg of
|
2023-11-26 11:58:20 -08:00
|
|
|
SetProgram prog -> ({ m | program = prog }, Cmd.none)
|
2023-11-26 12:47:05 -08:00
|
|
|
SetQuery query -> ({ m | query = query }, Cmd.none)
|
2023-11-30 21:29:37 -08:00
|
|
|
SetTab tab -> ({ m | tab = tab }, Cmd.none)
|
2023-12-01 11:31:38 -08:00
|
|
|
SetEditMode mode -> ({ m | editMode = mode }, Cmd.none)
|
2023-11-26 11:43:38 -08:00
|
|
|
|
|
|
|
subscriptions : Model -> Sub Msg
|
|
|
|
subscriptions _ = Sub.none
|
|
|
|
|
|
|
|
main =
|
|
|
|
Browser.element
|
|
|
|
{ init = init
|
|
|
|
, view = view
|
|
|
|
, update = update
|
|
|
|
, subscriptions = subscriptions
|
|
|
|
}
|
2023-11-26 15:54:01 -08:00
|
|
|
|
|
|
|
-- Latex support:
|
|
|
|
-- Based on https://stackoverflow.com/questions/75492820/embedding-mathematical-equations-in-an-elm-spa
|
|
|
|
|
|
|
|
latex : String -> Html Msg
|
|
|
|
latex expr =
|
|
|
|
Html.node "katex-expression"
|
|
|
|
[ Html.Attributes.attribute "expression" expr
|
|
|
|
, Html.Attributes.attribute "katex-options" (Json.Encode.encode 0 options)
|
|
|
|
]
|
|
|
|
[]
|
|
|
|
|
|
|
|
|
|
|
|
options : Json.Encode.Value
|
|
|
|
options =
|
|
|
|
Json.Encode.object
|
|
|
|
[ ( "displayMode", Json.Encode.bool True )
|
|
|
|
]
|