Skip to content

Commit

Permalink
WIP basilisp port
Browse files Browse the repository at this point in the history
  • Loading branch information
djblue committed Oct 31, 2024
1 parent 681fb64 commit 6c7be69
Show file tree
Hide file tree
Showing 25 changed files with 651 additions and 260 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ clojure.data.json*
*.iml

obj/

/py/
**__pycache__**
22 changes: 21 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,26 @@
":shadow"
]
}
}
},
{
"name": "basilisp",
"projectType": "deps.edn",
"projectRootPath": [
"."
],
"customJackInCommandLine": "./py/bin/basilisp nrepl-server",
"jackInEnv": {
"PYTHONPATH": "dev:src:test"
},
"nReplPortFile": [
".nrepl-port",
],
"menuSelections": {
"cljAliases": [
":dev",
":cider"
]
}
},
]
}
39 changes: 27 additions & 12 deletions src/examples/data.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
(:require #?(:clj [clojure.java.io :as io])
#?(:org.babashka/nbb [clojure.core]
:default [examples.hacker-news :as hn])
[clojure.pprint :as pp]
#?(:lpy [portal.runtime]
:default [clojure.pprint :as pp])
[examples.macros :refer [read-file]]
[portal.colors :as c]
[portal.viewer :as v])
Expand All @@ -13,7 +14,9 @@
:org.babashka/nbb (:import)
:cljs (:import [goog.math Long])
:cljr (:import [System DateTime Guid Uri]
[System.IO File])))
[System.IO File])
:lpy (:import [math :as Math]
[datetime :as datetime])))

#?(:clj
(defn slurp-bytes [x]
Expand Down Expand Up @@ -56,17 +59,23 @@
::uuid (random-uuid)
::date (js/Date.)
::bigint (js/BigInt "42")
::js-array #js [0 1 2 3 4]
::js-object #js {:hello "world"}}
::js-array (clj->js [0 1 2 3 4])
::js-object (clj->js {:hello "world"})}
:cljs
{::long (.fromString Long "4611681620380904123")
::promise (js/Promise.resolve 123)
::url (js/URL. "https://github.com/djblue/portal")
::uuid (random-uuid)
::date (js/Date.)
::bigint (js/BigInt "42")
::js-array #js [0 1 2 3 4]
::js-object #js {:hello "world"}}))
::js-array (clj->js [0 1 2 3 4])
::js-object (clj->js {:hello "world"})}
:lpy
{::promise (promise)
::uuid (random-uuid)
::date (datetime.datetime/now)
::py-list (python/list [0 1 2 3 4])
::py-dict (python/dict {"hello" "world"})}))

(def platform-collections
#?(:bb nil
Expand Down Expand Up @@ -107,11 +116,15 @@

(def clojure-data
{::regex #"hello-world"
::sorted-map (sorted-map-by gt 3 "c" 2 "b" 1 "a")
::sorted-set (sorted-set-by gt 3 2 1)
::sorted-map #?(:lpy nil
:default (sorted-map-by gt 3 "c" 2 "b" 1 "a"))
::sorted-set #?(:lpy nil
:default
(sorted-set-by gt 3 2 1))
::var #'portal.colors/themes
::with-meta (with-meta 'with-meta {:hello :world})
::tagged (tagged-literal 'my/tag ["hello, world"])
::tagged #?(:lpy nil
:default (tagged-literal 'my/tag ["hello, world"]))
{:example/settings 'complex-key} :hello-world
::atom (atom ::hello)
::function println
Expand Down Expand Up @@ -244,9 +257,11 @@
::different-value ::new-key}]))

(def diff-text-data
(v/diff-text
[(with-out-str (pp/pprint (first diff-data)))
(with-out-str (pp/pprint (second diff-data)))]))
#?(:lpy nil
:default
(v/diff-text
[(with-out-str (pp/pprint (first diff-data)))
(with-out-str (pp/pprint (second diff-data)))])))

(def string-data
(v/for
Expand Down
28 changes: 16 additions & 12 deletions src/examples/hacker_news.cljc
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
(ns examples.hacker-news
(:require #?(:clj [portal.sync :as a]
:cljs [portal.async :as a]
:cljr [portal.sync :as a])
:cljr [portal.sync :as a]
:lpy [portal.sync :as a])
#?(:cljs [examples.fetch :refer [fetch]])
[clojure.core.protocols :refer [nav]]
#?(:clj [portal.runtime.json :as json]
:cljr [portal.runtime.json :as json])))
:cljr [portal.runtime.json :as json]
:lpy [portal.runtime.json :as json])))

(def root "https://hacker-news.firebaseio.com/v0")

Expand Down Expand Up @@ -38,19 +39,22 @@
#?(:clj (-> url slurp json/read)
:cljs (-> (fetch url)
(.then #(js->clj (.parse js/JSON %) :keywordize-keys true)))
:cljr (-> url (slurp :enc "utf8") json/read)))
:cljr (-> url (slurp :enc "utf8") json/read)
:lpy (-> url slurp json/read)))

(defn as-url [s]
#?(:clj (java.net.URL. s)
:cljs (js/URL. s)
:cljr (System.Uri. s)))
:cljr (System.Uri. s)
:lpy s))

(defn as-date [^long timestamp]
#?(:clj (java.util.Date. timestamp)
:cljs (js/Date. timestamp)
:cljr (.DateTime
(System.DateTimeOffset/FromUnixTimeMilliseconds
timestamp))))
timestamp))
:lpy timestamp))

(declare nav-hn)
(declare nav-item)
Expand Down Expand Up @@ -82,32 +86,32 @@

(contains? item :kids)
(update :kids vary-meta assoc
`nav #'nav-item
'clojure.core.protocols/nav #'nav-item
:portal.viewer/default :portal.viewer/inspector)

(contains? item :submitted)
(update :submitted vary-meta assoc
`nav #'nav-item
'clojure.core.protocols/nav #'nav-item
:portal.viewer/default :portal.viewer/inspector)))))

(defn fetch-user [user]
(a/let [res (fetch-hn (str "/user/" user ".json"))]
(vary-meta res assoc `nav #'nav-hn)))
(vary-meta res assoc 'clojure.core.protocols/nav #'nav-hn)))

(defn nav-item [_coll _k v]
(a/let [res (fetch-hn (str "/item/" v ".json"))]
(vary-meta res assoc `nav #'nav-hn)))
(vary-meta res assoc 'clojure.core.protocols/nav #'nav-hn)))

(def stories
(with-meta
#{:topstories :newstories :beststories
:askstories :showstories :jobstories}
{`nav #'nav-hn
{'clojure.core.protocols/nav #'nav-hn
:portal.viewer/default :portal.viewer/inspector}))

(defn fetch-stories [type]
(a/let [res (fetch-hn (str "/" (name type) ".json"))]
(with-meta (take 15 res) (merge (meta res) {`nav #'nav-item}))))
(with-meta (take 15 res) (merge (meta res) {'clojure.core.protocols/nav #'nav-item}))))

(defn nav-hn [coll k v]
(cond
Expand Down
3 changes: 2 additions & 1 deletion src/examples/macros.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@

#?(:clj (defmacro read-file [file-name] (slurp file-name))
:cljs (defn read-file [_file-name] ::missing)
:cljr (defmacro read-file [file-name] (slurp file-name :enc "utf8")))
:cljr (defmacro read-file [file-name] (slurp file-name :enc "utf8"))
:lpy (defn read-file [file-name] (slurp file-name)))
6 changes: 4 additions & 2 deletions src/portal/api.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
[portal.runtime.jvm.commands])
#?(:clj [portal.runtime.jvm.launcher :as l]
:cljs [portal.runtime.node.launcher :as l]
:cljr [portal.runtime.clr.launcher :as l])
:cljr [portal.runtime.clr.launcher :as l]
:lpy [portal.runtime.py.launcher :as l])
#?(:clj [portal.sync :as a]
:cljs [portal.async :as a]
:cljr [portal.sync :as a])
:cljr [portal.sync :as a]
:lpy [portal.sync :as a])
#?(:clj [clojure.java.io :as io]
:cljs [portal.resources :as io])
[clojure.set :as set]
Expand Down
54 changes: 34 additions & 20 deletions src/portal/runtime.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
(:refer-clojure :exclude [read])
(:require #?(:clj [portal.sync :as a]
:cljr [portal.sync :as a]
:cljs [portal.async :as a])
:cljs [portal.async :as a]
:lpy [portal.sync :as a])
#?(:joyride [portal.runtime.datafy :refer [datafy nav]]
:org.babashka/nbb [portal.runtime.datafy :refer [datafy nav]]
:lpy [portal.runtime.datafy :refer [datafy nav]]
:default [clojure.datafy :refer [datafy nav]])
#?(:joyride [cljs.pprint :as pprint]
:default [clojure.pprint :as pprint])
Expand All @@ -15,6 +17,7 @@

#?(:joyride nil
:org.babashka/nbb nil
:lpy nil
:default
(defmethod pprint/simple-dispatch tagged-type [value]
(if (not= (:tag value) "remote")
Expand Down Expand Up @@ -74,7 +77,7 @@
(defn- hashable? [value]
(try
(and (hash value) true)
(catch #?(:clj Exception :cljr Exception :cljs :default) _
(catch #?(:clj Exception :cljr Exception :cljs :default :lpy Exception) _
false)))

#?(:bb (def clojure.lang.Range (type (range 1.0))))
Expand All @@ -96,7 +99,13 @@
(try (with-meta value {}) true
(catch :default _e false)))

:cljs (implements? IMeta value)))
:cljs (implements? IMeta value)

:lpy
(try (with-meta value {}) true
(catch Exception _e false))))

#?(:lpy (defn- sorted? [_] false))

(defn- hash+ [x]
(cond
Expand Down Expand Up @@ -138,7 +147,8 @@
:cljr (instance? clojure.lang.Atom o)
:joyride (= Atom (type o))
:org.babashka/nbb (= Atom (type o))
:cljs (satisfies? cljs.core/IAtom o)))
:cljs (satisfies? cljs.core/IAtom o)
:lpy (instance? basilisp.lang.atom/Atom o)))

(defn- notify [session-id a]
(when-let [request @request]
Expand Down Expand Up @@ -212,7 +222,7 @@

(defn- to-object [buffer value tag rep]
(if-not *session*
(cson/-to-json
(cson/to-json*
(with-meta
(cson/tagged-value "remote" (pr-str value))
(meta value))
Expand All @@ -235,9 +245,9 @@
:clj
(extend-type java.util.Collection
cson/ToJson
(-to-json [value buffer]
(to-json* [value buffer]
(if-let [id (value->id? value)]
(cson/-to-json (cson/tagged-value "ref" id) buffer)
(cson/to-json* (cson/tagged-value "ref" id) buffer)
(cson/tagged-coll
buffer
(cond
Expand All @@ -251,9 +261,9 @@
:clj
(extend-type java.util.Map
cson/ToJson
(-to-json [value buffer]
(to-json* [value buffer]
(if-let [id (value->id? value)]
(cson/-to-json (cson/tagged-value "ref" id) buffer)
(cson/to-json* (cson/tagged-value "ref" id) buffer)
(cson/tagged-map
buffer
"{"
Expand All @@ -264,15 +274,16 @@

(extend-type #?(:clj Object
:cljr Object
:cljs default)
:cljs default
:lpy python/object)
cson/ToJson
(-to-json [value buffer]
(to-json* [value buffer]
(to-object buffer value :object nil)))

(defn- has? [m k]
(try
(k m)
(catch #?(:clj Exception :cljr Exception :cljs :default) _e)))
(catch #?(:clj Exception :cljr Exception :lpy Exception :cljs :default) _e nil)))

(defn- no-cache [value]
(or (not (coll? value))
Expand Down Expand Up @@ -341,21 +352,24 @@

#_{:clj-kondo/ignore [:unused-private-var]}
(defn- runtime []
#?(:portal :portal :bb :bb :clj :clj :joyride :joyride :org.babashka/nbb :nbb :cljs :cljs :cljr :cljr))
#?(:portal :portal :bb :bb :clj :clj :joyride :joyride :org.babashka/nbb :nbb :cljs :cljs :cljr :cljr :lpy :py))

(defn- error->data [e]
#?(:clj (assoc (Throwable->map e) :runtime (runtime))
:cljr (assoc (Throwable->map e) :runtime (runtime))
:cljs e))
:default e))

(defn update-value [new-value]
(try
(realize-value! new-value)
(swap! tap-list conj new-value)
(catch #?(:clj Exception :cljr Exception :cljs :default) e
(catch #?(:clj Exception :cljr Exception :lpy Exception :cljs :default) e
(swap! tap-list conj
(error->data
(ex-info "Failed to receive value." {:value-type (type new-value)} e))))))
#?(:lpy
(ex-info "Failed to receive value." {:value-type (type new-value)})
:default
(ex-info "Failed to receive value." {:value-type (type new-value)} e)))))))

(def ^:private runtime-keymap (atom ^::no-cache {}))

Expand All @@ -372,6 +386,7 @@
#?(:bb "bb"
:clj "jvm"
:cljr "clr"
:lpy "py"
:joyride "joyride"
:org.babashka/nbb "nbb"
:cljs (cond
Expand Down Expand Up @@ -431,7 +446,7 @@
(cond-> out
(predicate v)
(assoc name result))
(catch #?(:clj Exception :cljr Exception :cljs :default) _ex out))
(catch #?(:cljs :default :default Exception) _ex out))
(assoc out name result)))))
{}
@registry)
Expand All @@ -453,7 +468,7 @@
(a/try
(a/let [return (binding [*session* session] (apply f args))]
(done (assoc (source-info f) :return return)))
(catch #?(:clj Exception :cljr Exception :cljs js/Error) e
(catch #?(:clj Exception :cljr Exception :cljs js/Error :default Exception) e
(done (assoc
(source-info f)
:error
Expand All @@ -462,8 +477,7 @@
{::function f
::args args
::found? (some? f)
::data (ex-data e)}
e)
::data (ex-data e)})
datafy
(assoc :runtime (runtime)))))))))

Expand Down
Loading

0 comments on commit 6c7be69

Please sign in to comment.