diff --git a/.nrepl-port b/.nrepl-port deleted file mode 100644 index afbb6ed..0000000 --- a/.nrepl-port +++ /dev/null @@ -1 +0,0 @@ -53855 \ No newline at end of file diff --git a/visualisers/gmvis/package-lock.json b/visualisers/gmvis/package-lock.json index 474a21a..10903af 100644 --- a/visualisers/gmvis/package-lock.json +++ b/visualisers/gmvis/package-lock.json @@ -9,14 +9,61 @@ "version": "0.0.1", "dependencies": { "ace-builds": "^1.32.7", - "react": "16.13.0", - "react-ace": "^10.1.0", - "react-dom": "16.13.0" + "react": "^18.3.0", + "react-ace": "11.0.1", + "react-dom": "18.3.0", + "react-resplit": "^1.3.1" }, "devDependencies": { "shadow-cljs": "2.28.3" } }, + "node_modules/@babel/runtime": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz", + "integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/ace-builds": { "version": "1.33.1", "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.33.1.tgz", @@ -900,28 +947,26 @@ } }, "node_modules/react": { - "version": "16.13.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.13.0.tgz", - "integrity": "sha512-TSavZz2iSLkq5/oiE7gnFzmURKZMltmi193rm5HEoUDAXpzT9Kzw6oNZnGoai/4+fUnm7FqS5dwgUL34TujcWQ==", + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.0.tgz", + "integrity": "sha512-RPutkJftSAldDibyrjuku7q11d3oy6wKOyPe5K1HA/HwwrXcEqBdHsLypkC2FFYjP7bPUa6gbzSBhw4sY2JcDg==", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" + "loose-envify": "^1.1.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/react-ace": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/react-ace/-/react-ace-10.1.0.tgz", - "integrity": "sha512-VkvUjZNhdYTuKOKQpMIZi7uzZZVgzCjM7cLYu6F64V0mejY8a2XTyPUIMszC6A4trbeMIHbK5fYFcT/wkP/8VA==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/react-ace/-/react-ace-11.0.1.tgz", + "integrity": "sha512-ulk2851Fx2j59AAahZHTe7rmQ5bITW1xytskAt11F8dv3rPLtdwBXCyT2qSbRnJvOq8UpuAhWO4/JhKGqQBEDA==", "dependencies": { - "ace-builds": "^1.4.14", + "ace-builds": "^1.32.8", "diff-match-patch": "^1.0.5", "lodash.get": "^4.4.2", "lodash.isequal": "^4.5.0", - "prop-types": "^15.7.2" + "prop-types": "^15.8.1" }, "peerDependencies": { "react": "^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0", @@ -929,17 +974,15 @@ } }, "node_modules/react-dom": { - "version": "16.13.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.0.tgz", - "integrity": "sha512-y09d2c4cG220DzdlFkPTnVvGTszVvNpC73v+AaLGLHbkpy3SSgvYq8x0rNwPJ/Rk/CicTNgk0hbHNw1gMEZAXg==", + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-zaKdLBftQJnvb7FtDIpZtsAIb2MZU087RM8bRDZU8LVCCFYjPTsDZJNFUWPcVz3HFSN1n/caxi0ca4B/aaVQGQ==", "dependencies": { "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.0" + "scheduler": "^0.23.1" }, "peerDependencies": { - "react": "^16.0.0" + "react": "^18.3.0" } }, "node_modules/react-is": { @@ -947,6 +990,18 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/react-resplit": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/react-resplit/-/react-resplit-1.3.1.tgz", + "integrity": "sha512-i1sYitKd3spooCOpDw5IH7STsE6g8jC/UgEWrSGjTG+GISr5PmLpGkWws2ean7ESTS5bXfScCHCs8QusivwZrw==", + "dependencies": { + "@radix-ui/react-slot": "^1.0.2" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -986,6 +1041,11 @@ "node": ">= 0.8.0" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, "node_modules/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -1017,12 +1077,11 @@ ] }, "node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.1.tgz", + "integrity": "sha512-5GKS5JGfiah1O38Vfa9srZE4s3wdHbwjlCrvIookrg2FO9aIwKLOJXuJQFlEfNcVSOXuaL2hzDeY20uVXcUtrw==", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "node_modules/set-function-length": { diff --git a/visualisers/gmvis/package.json b/visualisers/gmvis/package.json index abc6425..39e9816 100644 --- a/visualisers/gmvis/package.json +++ b/visualisers/gmvis/package.json @@ -1 +1 @@ -{"name":"gmvis","version":"0.0.1","private":true,"devDependencies":{"shadow-cljs":"2.28.3"},"dependencies":{"ace-builds":"^1.32.7","react":"16.13.0","react-ace":"^10.1.0","react-dom":"16.13.0"}} \ No newline at end of file +{"name":"gmvis","version":"0.0.1","private":true,"devDependencies":{"shadow-cljs":"2.28.3"},"dependencies":{"ace-builds":"^1.32.7","react":"^18.3.0","react-ace":"11.0.1","react-dom":"18.3.0","react-resplit":"^1.3.1"}} \ No newline at end of file diff --git a/visualisers/gmvis/public/css/main.css b/visualisers/gmvis/public/css/main.css new file mode 100644 index 0000000..f6a306e --- /dev/null +++ b/visualisers/gmvis/public/css/main.css @@ -0,0 +1,32 @@ +@import "solarized-light.css"; + +html, body, #mount +{ height: 100% +; width: 100% +} + +body +{ max-width: 90% +; margin: 0 auto +; padding: 0 +} + +.split-root +{ height: 100% +} + +.split-splitter +{ width: 100% +; height: 100% +; background: #ccc +} + +.split-pane +{ margin: 0 +; padding: 0 +} + +.pane-content +{ margin: 0.5em +} + diff --git a/visualisers/gmvis/public/css/solarized-light.css b/visualisers/gmvis/public/css/solarized-light.css new file mode 100644 index 0000000..50af0a3 --- /dev/null +++ b/visualisers/gmvis/public/css/solarized-light.css @@ -0,0 +1,304 @@ +@import url(http://fonts.googleapis.com/css?family=Inconsolata); +@import url(http://fonts.googleapis.com/css?family=PT+Sans); +@import url(http://fonts.googleapis.com/css?family=PT+Sans+Narrow:400,700); +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section, +summary { + display: block; +} +audio, +canvas, +video { + display: inline-block; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden] { + display: none; +} +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +a:focus { + outline: thin dotted; +} +a:active, +a:hover { + outline: 0; +} +h1 { + font-size: 2em; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +mark { + background: #ff0; + color: #000; +} +code, +kbd, +pre, +samp { + font-family: monospace, serif; + font-size: 1em; +} +pre { + white-space: pre-wrap; + word-wrap: break-word; +} +q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; + width: 100%; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 0; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +button, +input, +select, +textarea { + font-family: inherit; + font-size: 100%; + margin: 0; +} +button, +input { + line-height: normal; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +input[disabled] { + cursor: default; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +textarea { + overflow: auto; + vertical-align: top; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +html { + font-family: 'PT Sans', sans-serif; +} +pre, +code { + font-family: 'Inconsolata', sans-serif; +} +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: 'PT Sans Narrow', sans-serif; + font-weight: 700; +} +html { + background-color: #eee8d5; + color: #657b83; + margin: 1em; +} +body { + background-color: #fdf6e3; + margin: 0 auto; + max-width: 23cm; + border: 1pt solid #93a1a1; + padding: 1em; +} +code { + background-color: #eee8d5; + padding: 2px; +} +a { + color: #b58900; +} +a:visited { + color: #cb4b16; +} +a:hover { + color: #cb4b16; +} +h1 { + color: #d33682; +} +h2, +h3, +h4, +h5, +h6 { + color: #859900; +} +pre { + background-color: #fdf6e3; + color: #657b83; + border: 1pt solid #93a1a1; + padding: 1em; + box-shadow: 5pt 5pt 8pt #eee8d5; +} +pre code { + background-color: #fdf6e3; +} +h1 { + font-size: 2.8em; +} +h2 { + font-size: 2.4em; +} +h3 { + font-size: 1.8em; +} +h4 { + font-size: 1.4em; +} +h5 { + font-size: 1.3em; +} +h6 { + font-size: 1.15em; +} +.tag { + background-color: #eee8d5; + color: #d33682; + padding: 0 0.2em; +} +.todo, +.next, +.done { + color: #fdf6e3; + background-color: #dc322f; + padding: 0 0.2em; +} +.tag { + -webkit-border-radius: 0.35em; + -moz-border-radius: 0.35em; + border-radius: 0.35em; +} +.TODO { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #2aa198; +} +.NEXT { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #268bd2; +} +.ACTIVE { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #268bd2; +} +.DONE { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #859900; +} +.WAITING { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #cb4b16; +} +.HOLD { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #d33682; +} +.NOTE { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #d33682; +} +.CANCELLED { + -webkit-border-radius: 0.2em; + -moz-border-radius: 0.2em; + border-radius: 0.2em; + background-color: #859900; +} diff --git a/visualisers/gmvis/public/index.html b/visualisers/gmvis/public/index.html index 8ca598a..e6a867f 100644 --- a/visualisers/gmvis/public/index.html +++ b/visualisers/gmvis/public/index.html @@ -11,6 +11,8 @@ +
+
diff --git a/visualisers/gmvis/src/main.cljs b/visualisers/gmvis/src/main.cljs index 9b26d1d..dba7c4e 100644 --- a/visualisers/gmvis/src/main.cljs +++ b/visualisers/gmvis/src/main.cljs @@ -1,31 +1,28 @@ (ns main (:require - ["react-ace$default" :as AceEditor] - ["ace-builds/src-noconflict/mode-haskell"] - ["ace-builds/src-noconflict/theme-solarized_light"] - ["ace-builds/src-noconflict/keybinding-vim"] + [ui :as ui] [wscljs.client :as ws] [wscljs.format :as fmt] [clojure.string :as str] - [cljs.core.match :refer-macros [match]])) + [cljs.core.match :refer-macros [match]] + [reagent.dom :as rdom])) -(defn display-errors [es] - (doseq [{{e :contents} :diagnostic} es] - (let [fmte (map #(str " • " % "\n") e)] - (js/console.warn (apply str "message from rlpc:\n" fmte))))) +;------------------------------------------------------------------------------; + +(def *rlp-socket nil) + +;------------------------------------------------------------------------------; (defn on-message [e] (let [r (js->clj (js/JSON.parse (.-data e)) :keywordize-keys true)] (match r {:tag "Evaluated" :contents c} - (prn c) + (reset! ui/current-evaluation c) :else (js/console.warn "unrecognised response from rlp")))) -(def +rlp-socket+ nil) - (defn send [msg] - (ws/send +rlp-socket+ msg fmt/json)) + (ws/send *rlp-socket msg fmt/json)) (defn on-open [] (println "socket opened") @@ -39,7 +36,7 @@ "main = fac 3;"])})) (defn init-rlp-socket [] - (set! +rlp-socket+ (ws/create "ws://127.0.0.1:9002" + (set! *rlp-socket (ws/create "ws://127.0.0.1:9002" {:on-message on-message :on-open on-open :on-close #(println "socket closed") @@ -47,12 +44,14 @@ ;; this is called before any code is reloaded (defn ^:dev/before-load stop [] - (ws/close +rlp-socket+) + (ws/close *rlp-socket) (js/console.log "stop")) ;; start is called by init and after code reloading finishes (defn ^:dev/after-load start [] (js/console.log "start") + (rdom/render [ui/Main] + (js/document.getElementById "mount")) (init-rlp-socket)) ;; init is called ONCE when the page loads diff --git a/visualisers/gmvis/src/ui.cljs b/visualisers/gmvis/src/ui.cljs new file mode 100644 index 0000000..0aee7cd --- /dev/null +++ b/visualisers/gmvis/src/ui.cljs @@ -0,0 +1,80 @@ +(ns ui + (:require + [wscljs.client :as ws] + [wscljs.format :as fmt] + [clojure.string :as str] + [cljs.core.match :refer-macros [match]] + ["react-ace$default" :as AceEditor] + ["react-resplit" :refer (Resplit)] + ["ace-builds/src-noconflict/mode-haskell"] + ["ace-builds/src-noconflict/theme-solarized_light"] + ["ace-builds/src-noconflict/keybinding-vim"] + [reagent.core :as r] + [reagent.dom :as rdom])) + +;------------------------------------------------------------------------------; + +(def current-evaluation (r/atom [])) +(def current-index (r/atom 0)) + +(def +split-width+ "4px") + +;------------------------------------------------------------------------------; + +(defn Root [props & children] + [:> Resplit.Root (assoc props :class "split-root") + [:<> children]]) + +(defn Pane [props & children] + [:> Resplit.Pane (assoc props :class "split-pane") + [:<> children]]) + +(defn Splitter [props & children] + [:> Resplit.Splitter (assoc props :class "split-splitter") + [:<> children]]) + +;------------------------------------------------------------------------------; + +(defn Stack [] + [:div {:class "pane-content"} + [:h1 "Stack"]]) + +(defn Dump [] + [:div {:class "pane-content"} + [:h1 "Dump"]]) + +(defn Heap [] + [:div {:class "pane-content"} + [:h1 "Heap"]]) + +(defn Code [] + [:div {:class "pane-content"} + [:h1 "Code"]]) + +;------------------------------------------------------------------------------; + +(defn GM [{st :st}] + [Root {:direction "horizontal"} + [Pane {:order 0 :initialSize "0.333fr"} + [Heap]] + [Splitter {:order 1 :size +split-width+}] + [Pane {:order 2 :initialSize "0.333fr"} + [Root {:direction "vertical"} + [Pane {:order 0 :initialSize "0.8fr"} + [Stack]] + [Splitter {:order 1 :size +split-width+}] + [Pane {:order 2 :initialSize "0.2fr"} + [Code]]]] + [Splitter {:order 3 :size +split-width+}] + [Pane {:order 5 :initialSize "0.333fr"} + [Dump]]]) + +(defn Main [] + (prn @current-evaluation) + (prn @current-index) + (if-let [st (nth @current-evaluation + @current-index + nil)] + [GM {:st st}] + [:h1 "no evaluation"])) +