type-checker and working visualiser

This commit is contained in:
crumbtoo
2024-03-18 10:27:06 -06:00
parent e3d7c49370
commit 3bc9dbb431
6 changed files with 211 additions and 69 deletions

View File

@@ -1,41 +1,46 @@
(ns hmvis.annotated
(:require [cljs.core.match :refer-macros [match]]
; [cljsx.core :refer [jsx> react> defcomponent]]
; [react :as react]
; [react-dom :as react-dom]
[cljsx.core :refer [jsx> react> defcomponent]]
[react :as react]
[react-dom :as react-dom]
[reagent.core :as r]
[reagent.dom :as rdom]
[clojure.pprint :refer [cl-format]]))
[clojure.pprint :refer [cl-format]]
[hmvis.ppr :as ppr]))
(defonce tc-input (r/atom nil))
(defonce current-annotation-text (r/atom nil))
(def app-prec 10)
(def app-prec1 11)
(defn hsep [& as]
(let [f (fn [a b] (str a " " b))]
(reduce f as)))
; (defn maybe-parens [c s]
; (if c
; (react> (<> "(" s ")"))
; s))
(defn maybe-parens [c s]
(if c
[:<> "(" s ")"]
s))
(defn formatln [fs & rest]
(apply cl-format true (str fs "~%") rest))
(defn Typed [t & children]
(formatln "type: ~S" t)
[:div {:class "annotation-wrapper"
:onMouseEnter #(do (println "doge")
(reset! current-annotation-text "doge"))
:onMouseLeave #(reset! current-annotation-text nil)}
children])
(defn Annotation [text visible?]
(if visible?
[:div {:class "annotation"}
text]
nil))
(defn Annotation []
[:p (or @current-annotation-text "<nil>")])
(def nesting-rainbow (cycle ["red" "orange" "yellow"
"green" "blue" "purple"]))
(defn Typed [t child]
(let [hovering? (r/atom false)]
(fn []
[:div {:class "annotation-wrapper"
:on-mouse-enter #(reset! hovering? true)
:on-mouse-leave #(reset! hovering? false)}
child
[Annotation t @hovering?]])))
(declare Expr)
@@ -49,18 +54,20 @@
[:code var-id])
(defn AppExpr [f x]
[:<> [Expr app-prec f]
[:<> [Expr ppr/app-prec f]
" "
[Expr app-prec1 x]])
[Expr ppr/app-prec1 x]])
(defn Expr [p {e :e t :type}]
(match e
{:InL {:tag "LamF" :contents [bs body & _]}}
[LambdaExpr bs body]
(maybe-parens (< ppr/app-prec1 p)
[Typed t [LambdaExpr bs body]])
{:InL {:tag "VarF" :contents var-id}}
[VarExpr var-id]
[Typed t [VarExpr var-id]]
{:InL {:tag "AppF" :contents [f x]}}
[AppExpr f x]
(maybe-parens (< ppr/app-prec p)
[Typed t [AppExpr f x]])
:else [:code "<expr>"]))
(defn render-decl [{name :name body :body}]
@@ -68,23 +75,11 @@
(str name " = ") [Expr 0 body] #_ (render-expr body)
[:br]])
(defn Thing []
[:h1 @current-annotation-text])
(defn type-checker []
[:div
[Thing]
#_ [:button {:on-click #(reset! current-annotation-text "doge")}]])
; (defcomponent TypeChecker props
; (react>
; (<div>
; (<Thing>)
; (<button :onClick #(do (reset! current-annotation-text "doge")
; (formatln "thing: ~S" @current-annotation-text)) >)
; #_ (map render-decl (or @tc-input [])))))
(map render-decl (or @tc-input []))])
(defn init []
(rdom/render [type-checker]
(js/document.querySelector "#type-check")))
(js/document.querySelector "#output")))

View File

@@ -0,0 +1,41 @@
(ns hmvis.ppr
(:require [cljs.core.match :refer-macros [match]]))
(def app-prec 10)
(def app-prec1 11)
(defn- maybe-parens [c s]
(if c
(str "(" s ")")
s))
(defn- hsep [& as]
(let [f (fn [a b] (str a " " b))]
(reduce f as)))
(declare expr)
(defn lambda-expr [binds body]
(hsep "λ" (apply hsep binds) "->" (expr body)))
(defn app-expr [f x]
(hsep (expr app-prec f) (expr app-prec1 x)))
(defn var-expr [var-id]
var-id)
(defn expr
([exp] (expr 0 exp))
([p {e :e}]
(match e
{:InL {:tag "LamF" :contents [bs body & _]}}
(maybe-parens (< app-prec1 p)
(lambda-expr bs body))
{:InL {:tag "VarF" :contents var-id}}
(var-expr var-id)
{:InL {:tag "AppF" :contents [f x]}}
(maybe-parens (< app-prec p)
(app-expr f x))
:else [:code "<expr>"])))