diff --git a/visualisers/gmvis/public/css/main.css b/visualisers/gmvis/public/css/main.css index 5cfc8c7..134a342 100644 --- a/visualisers/gmvis/public/css/main.css +++ b/visualisers/gmvis/public/css/main.css @@ -25,35 +25,49 @@ body { margin: 0 ; padding: 0 ; overflow: scroll +; display: flex +; flex-direction: column } .pane-content { margin: 0.5em } -.pane-content h5 +.view-header { margin: 0 -} - -.split-pane:has(> .stack-view) -{ display: flex -; flex-direction: column-reverse +; flex-shrink: 0 } .stack-view { display: flex +; flex-direction: column +; justify-content: space-between + +/* to fill the container */ +; flex-grow: 1 +} + +.stack-entry-container +{ display: flex ; flex-direction: column-reverse ; align-content: flex-end } -.stack-view > .stack-entry:nth-of-type(odd) +.stack-entry-container.even > .stack-entry:nth-of-type(even) { background: #0000007f +; color: white +} + +.stack-entry-container.odd > .stack-entry:nth-of-type(odd) +{ background: #0000007f +; color: white } .stack-entry { display: flex ; flex-direction: row ; justify-content: space-between +; font-family: monospace; } .stack-entry-addr @@ -67,14 +81,46 @@ body .heap-view {} +/* .split-pane:has(> .code-view) */ +/* { overflow: hidden */ +/* } */ + .code-view +{ display: flex +; flex-direction: column +; align-items: stretch +; align-content: stretch +; justify-content: flex-start +; flex-grow: 1 +} + +.code-view .code-instr-container { display: grid +; overflow: scroll +; flex-shrink: 4 +; min-height: 0 } -.code-view.instr -{} +.code-view .instr +{ font-family: monospace; +} -.code-view > .instr:nth-of-type(odd) +.code-instr-container.even > .instr:nth-of-type(even) { background: #0000007f +; color: white +} + +.code-instr-container.odd > .instr:nth-of-type(odd) +{ background: #0000007f +; color: white +} + +.code-view .code-button-container +{ display: flex +; flex-direction: row +/* ; align-self: flex-end */ +; justify-content: space-between +; margin-top: auto +; flex-shrink: 0 } diff --git a/visualisers/gmvis/src/ui.cljs b/visualisers/gmvis/src/ui.cljs index 19d040c..2d77719 100644 --- a/visualisers/gmvis/src/ui.cljs +++ b/visualisers/gmvis/src/ui.cljs @@ -15,7 +15,8 @@ ;------------------------------------------------------------------------------; (def current-evaluation (r/atom [])) -(def current-index (r/atom 5)) +; (def current-index (r/atom 5)) +(defonce current-index (r/atom 0)) (def +split-width+ "4px") @@ -33,47 +34,87 @@ [:> Resplit.Splitter (assoc props :class "split-splitter") [:<> children]]) +(defn Header [text] + [:h5 {:class "view-header"} + text]) + ;------------------------------------------------------------------------------; (defn Dump [] [:div {:class "pane-content dump-view"} - [:h1 "Dump"]]) + [Header "Dump"]]) (defn Heap [] [:div {:class "pane-content heap-view"} - [:h1 "Heap"]]) + [Header "Heap"]]) + +(defn gen-key [] + (js/self.crypto.randomUUID)) + +(defn add-key [e] + (let [uuid (js/self.crypto.randomUUID)] + (match e + [tag props & children] (concat [tag (assoc props :key uuid)] children)))) ;------------------------------------------------------------------------------; (defn deref-addr [heap addr] (get heap (keyword (str addr)) - (str ""))) + nil)) (defn words [& ws] (->> ws (map str) (str/join \space))) -(defn ppr-node [heap n] - (match n +(defn maybe-parens [c s] + (if c + (str "(" s ")") + s)) + +(def app-prec 10) +(def app-prec+1 11) +(def app-prec-1 9) + +(defn ppr-node* [p heap addr] + (match (deref-addr heap addr) {:tag "NGlobal" :contents [arity code]} - (words "Global" arity "") + (maybe-parens (> p 0) + (words "Global" arity "")) {:tag "NNum" :contents k} - (words "Num" k) + (maybe-parens (> p 0) + (words "Num" k)) + + {:tag "NAp" :contents [f x]} + (maybe-parens (> p app-prec) + (words "App" + (ppr-node* app-prec heap f) + (ppr-node* app-prec+1 heap x))) + + nil (str "") + a (str "other" a))) +(defn ppr-node [heap addr] + (ppr-node* 0 heap addr)) + (defn StackEntry [heap addr] - (let [node (deref-addr heap addr)] - [:div {:class "stack-entry"} - (ppr-node heap node) - [:div {:class "stack-entry-addr"} - (str "&" addr)]])) + [:div {:class "stack-entry" + :key (gen-key)} + (ppr-node heap addr) + [:div {:class "stack-entry-addr"} + (str "&" addr)]]) + +(defn StackEntryContainer [children] + [:div {:class "stack-entry-container even"} + [:<> children]]) (defn Stack [heap s] [:div {:class "pane-content stack-view"} - [:<> (map (partial StackEntry heap) s)]]) + [Header "Stack"] + [StackEntryContainer (map (partial StackEntry heap) (reverse s))]]) #_ (swap! current-index #(+ % 1)) #_ (swap! current-index #(- % 1)) @@ -81,16 +122,34 @@ ;------------------------------------------------------------------------------; (defn ppr-instr [{op :tag c :contents}] - (str op " " c)) + (match op + "CaseJump" (words op "") + _ (words op c))) (defn Instr [instr] - [:code {:class "instr"} + [:code {:class "instr" + :key (gen-key)} (ppr-instr instr)]) +(defn CodeButtons [] + [:div {:class "code-button-container"} + [:button {:onClick #(swap! current-index dec)} + "<"] + [:code @current-index] + [:button {:onClick #(swap! current-index inc)} + ">"]]) + +(defn CodeInstrContainer [children] + [:div {:class (if (even? (count children)) + "code-instr-container even" + "code-instr-container odd")} + [:<> children]]) + (defn Code [code] [:div {:class "pane-content code-view"} - [:h5 "Next instructions"] - [:<> (map Instr code)]]) + [Header "Next instructions"] + [CodeInstrContainer (map Instr code)] + [CodeButtons]]) ;------------------------------------------------------------------------------;