121 lines
4.0 KiB
Elm
121 lines
4.0 KiB
Elm
module SeqSim.Render exposing (view)
|
|
import SeqSim.Model exposing (Model, Msg(..))
|
|
import SeqSim.Parser exposing (parse, vars, valid, varsValid, Prog, Source(..))
|
|
import SeqSim.Evaluator exposing (..)
|
|
import Maybe.Extra exposing (combine)
|
|
import List.Extra exposing (zip, getAt)
|
|
import Tuple exposing (second)
|
|
import Html exposing (Html, text, textarea, input, label, small, div, span, button, a, h1, h2, h3, h4, h5, br)
|
|
import Html.Attributes exposing (class, classList, id, for, type_, value, href)
|
|
import Html.Events exposing (onClick, onInput)
|
|
|
|
view : Model -> List (Html Msg)
|
|
view m =
|
|
[ div [ class "container" ]
|
|
[ h1 [] [ text "Sequential Consistency Simulator" ]
|
|
, viewProgs m.programs
|
|
, viewOutcomes m
|
|
]
|
|
]
|
|
|
|
toolbar : Html Msg
|
|
toolbar = div [ class"btn-group" ]
|
|
[ button
|
|
[ type_ "button"
|
|
, class "btn btn-primary"
|
|
, onClick AddProgram ]
|
|
[ text "Add Program" ]
|
|
]
|
|
|
|
viewProgs : List String -> Html Msg
|
|
viewProgs ps = div []
|
|
[ h2 [] [ text "Programs" ]
|
|
, toolbar
|
|
, div [ class "mt-2 row row-cols-1 row-cols-md-2 row-cols-lg-4" ]
|
|
<| List.indexedMap viewProg ps
|
|
]
|
|
|
|
viewProg : Int -> String -> Html Msg
|
|
viewProg i s = div [ class "col mb-2" ]
|
|
[ div [ class "card" ]
|
|
[ div [ class "card-body" ]
|
|
[ h5 [ class "card-title" ] [ text <| "Program " ++ String.fromInt (i+1) ]
|
|
, viewProgValidity s
|
|
, textarea [ class "mt-2 mb-2 form-control", onInput (ChangeProgram i), value s ] [ ]
|
|
, a [ class "btn btn-outline-danger", onClick (DeleteProgram i) ] [ text "Remove" ]
|
|
]
|
|
]
|
|
]
|
|
|
|
viewProgValidity : String -> Html Msg
|
|
viewProgValidity s =
|
|
if valid s
|
|
then span [ class "text-success" ] [ text "Valid" ]
|
|
else span [ class "text-danger" ] [ text "Invalid" ]
|
|
|
|
viewOutcomes : Model -> Html Msg
|
|
viewOutcomes m = div []
|
|
[ h2 [] [ text "Possible Outcomes" ]
|
|
, div [ class "form-group" ]
|
|
[ label [ for "variables" ] [ text "Interesting Variables" ]
|
|
, input
|
|
[ type_ "text"
|
|
, id "variables"
|
|
, class "form-control"
|
|
, if String.isEmpty m.variables
|
|
then classList []
|
|
else if varsValid m.variables then class "is-valid" else class "is-invalid"
|
|
, value m.variables
|
|
, onInput ChangeVariables
|
|
] []
|
|
, small [ class "form-text text-muted" ]
|
|
[ text "Enter the variables you want included in the final outcomes, separated by a comma."
|
|
]
|
|
]
|
|
, viewOutcomeTable m
|
|
]
|
|
|
|
viewOutcomeTable : Model -> Html Msg
|
|
viewOutcomeTable m =
|
|
case (vars m.variables, combine <| List.map parse m.programs) of
|
|
(Just (x::xs), Just ps) ->
|
|
let all = allOutcomes (x::xs) ps
|
|
in div [ class "card" ] <| List.singleton <| div [ class "card-body" ]
|
|
[ div [ class "row" ]
|
|
[ div [ class "col border-right col-auto" ]
|
|
<| List.indexedMap (viewRow (x::xs))
|
|
<| List.map second all
|
|
, div [ class "col" ] <|
|
|
case Maybe.andThen (\i -> getAt i all) m.selected of
|
|
Nothing -> []
|
|
Just (p, o) ->
|
|
[ viewProgStr p
|
|
]
|
|
]
|
|
]
|
|
_ -> div [] []
|
|
|
|
viewRow : List String -> Int -> List Int -> Html Msg
|
|
viewRow xs i vs = div []
|
|
[ a [ href "#", onClick (SelectOutcome i) ]
|
|
[ text <| stringFromOutcome xs vs
|
|
]
|
|
]
|
|
|
|
stringFromOutcome : List String -> List Int -> String
|
|
stringFromOutcome xs vs = List.map2 (\x v -> x ++ " = " ++ String.fromInt v) xs vs
|
|
|> String.join ", "
|
|
|
|
viewProgStr : Prog -> Html Msg
|
|
viewProgStr p =
|
|
let
|
|
sourceStr s =
|
|
case s of
|
|
Var x -> x
|
|
Const i -> String.fromInt i
|
|
in
|
|
List.map (\(x, s) -> text <| x ++ " = " ++ sourceStr s) p
|
|
|> List.intersperse (br [] [])
|
|
|> div []
|
|
|