Support satisfies? on protocol values (#1076)

This commit is contained in:
Michiel Borkent 2021-11-24 17:38:38 +01:00 committed by GitHub
parent a95c51998f
commit e419c569a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 49 deletions

2
sci

@ -1 +1 @@
Subproject commit 0bdd57d66da35d7a9c7ea3b10666a6b4b786808a
Subproject commit 3b62462112bde39d166914d0e424075ed18195cf

View file

@ -1,3 +1,4 @@
(ns aaaa-this-has-to-be-first.because-patches
;; we need pprint loaded first, it patches pprint to not bloat the GraalVM binary
(:require [babashka.impl.pprint]))
(:require [babashka.impl.patches.datafy]
[babashka.impl.pprint]))

View file

@ -316,6 +316,10 @@
java.util.Random
java.util.regex.Matcher
java.util.regex.Pattern
java.util.ArrayDeque
java.util.ArrayList
java.util.Collections
java.util.Comparator
java.util.Base64
java.util.Base64$Decoder
java.util.Base64$Encoder
@ -323,6 +327,7 @@
java.util.Locale
java.util.Map
java.util.MissingResourceException
java.util.NoSuchElementException
java.util.Optional
java.util.Properties
java.util.Set

View file

@ -1,46 +1,10 @@
(ns babashka.impl.datafy
{:no-doc true}
(:refer-clojure :exclude [create-ns])
(:require [babashka.impl.common :refer [ctx]]
[babashka.impl.protocols :as protocols]
[clojure.core.protocols :as p]
[clojure.datafy] ;; ensure datafy is loaded, we're going to override
;; its clojure.lang.Namespace implementation for
;; datafy
[clojure.reflect]
[sci.core :as sci :refer [copy-var]]
[sci.impl.namespaces :refer [sci-ns-name sci-ns-publics sci-ns-imports sci-ns-interns]]
[sci.impl.vars])
(:import [sci.impl.vars SciNamespace]))
(defn- sortmap [m]
(into (sorted-map) m))
;; Overrides for what is defined in clojure.datafy
(extend-protocol p/Datafiable
clojure.lang.Namespace
(datafy [n]
;; Override this with the default Object implementation. It bloats bb with 30mb and memory usage of GraalVM will peak!
#_(with-meta {:name (.getName n)
:publics (-> n ns-publics sortmap)
:imports (-> n ns-imports sortmap)
:interns (-> n ns-interns sortmap)}
(meta n))
n)
java.lang.Class
(datafy [c]
;; Statically use clojure.reflect instead of leaning on requiring-resolve
(let [{:keys [members] :as ret} (clojure.reflect/reflect c)]
(assoc ret :name (-> c .getName symbol) :members (->> members (group-by :name) sortmap)))))
(extend-protocol p/Datafiable
SciNamespace
(datafy [n]
(with-meta {:name (sci-ns-name n)
:publics (->> n (sci-ns-publics @ctx) sortmap)
:imports (->> n (sci-ns-imports @ctx) sortmap)
:interns (->> n (sci-ns-interns @ctx) sortmap)}
(meta n))))
(:require
[babashka.impl.protocols :as protocols]
[sci.core :as sci :refer [copy-var]]
[sci.impl.vars]))
(def datafy-ns (sci/create-ns 'clojure.datafy nil))

View file

@ -0,0 +1,38 @@
(ns babashka.impl.patches.datafy
(:require [babashka.impl.common :refer [ctx]]
[clojure.core.protocols :as p]
[clojure.datafy]
;; ensure datafy is loaded, we're going to override its
;; clojure.lang.Namespace implementation for datafy
[clojure.reflect]
[sci.impl.namespaces :refer [sci-ns-name sci-ns-publics sci-ns-imports sci-ns-interns]]
[sci.impl.vars])
(:import [sci.impl.vars SciNamespace]))
(defn- sortmap [m]
(into (sorted-map) m))
(extend-protocol p/Datafiable
clojure.lang.Namespace
(datafy [n]
;; Override this with the default Object implementation. It bloats bb with 30mb and memory usage of GraalVM will peak!
#_(with-meta {:name (.getName n)
:publics (-> n ns-publics sortmap)
:imports (-> n ns-imports sortmap)
:interns (-> n ns-interns sortmap)}
(meta n))
n)
java.lang.Class
(datafy [c]
;; Statically use clojure.reflect instead of leaning on requiring-resolve
(let [{:keys [members] :as ret} (clojure.reflect/reflect c)]
(assoc ret :name (-> c .getName symbol) :members (->> members (group-by :name) sortmap)))))
(extend-protocol p/Datafiable
SciNamespace
(datafy [n]
(with-meta {:name (sci-ns-name n)
:publics (->> n (sci-ns-publics @ctx) sortmap)
:imports (->> n (sci-ns-imports @ctx) sortmap)
:interns (->> n (sci-ns-interns @ctx) sortmap)}
(meta n))))

View file

@ -1,7 +1,13 @@
(ns babashka.impl.protocols
(:require [clojure.datafy :as d]
(:require [babashka.impl.protocols :as protocols]
[clojure.core.protocols :as p]
[clojure.datafy :as d]
;; ensure datafy is loaded, we're going to override its
;; clojure.lang.Namespace implementation for datafy
[clojure.reflect]
[sci.core :as sci :refer [copy-var]]
[sci.impl.types :as types]))
[sci.impl.types :as types]
[sci.impl.vars]))
;;;; datafy
@ -26,13 +32,30 @@
;; note: Clojure itself will handle checking metadata for impls
(d/nav coll k v))
;;;; sci namespace
(def protocols-ns (sci/create-ns 'clojure.core.protocols nil))
(def protocols-namespace
{'Datafiable (sci/new-var 'clojure.core.protocols/Datafiable {:methods #{'datafy}
:ns protocols-ns} {:ns protocols-ns})
{;; Datafiable
'Datafiable (sci/new-var 'clojure.core.protocols/Datafiable {:methods #{'datafy}
:protocol p/Datafiable
:ns protocols-ns}
{:ns protocols-ns})
'datafy (copy-var datafy protocols-ns)
;; Navigable
'Navigable (sci/new-var 'clojure.core.protocols/Navigable {:methods #{'nav}
:ns protocols-ns} {:ns protocols-ns})
'nav (copy-var nav protocols-ns)})
:protocol p/Navigable
:ns protocols-ns}
{:ns protocols-ns})
'nav (copy-var nav protocols-ns)
;; IKVReduce only added for satisies? check for now. We can implement
;; kv-reduce in the future, but this needs patching some functions like
;; update-vals, etc.
'IKVReduce (sci/new-var 'clojure.core.protocols/IKVReduce {:protocol p/IKVReduce
;; :methods #{'kv-reduce}
:ns protocols-ns}
{:ns protocols-ns})
;; 'kv-reduce (copy-var kv-reduce protocols-ns)
}
)

View file

@ -792,6 +792,11 @@ true")))
(deftest InetAddress-test
(is (= "192.168.2.2" (bb nil "(-> (java.net.InetAddress/getByName \"192.168.2.2\") (.getHostAddress))"))))
(deftest satisfies-protocols-test
#_(is (true? (bb nil "(satisfies? clojure.core.protocols/Datafiable {})")))
#_(is (true? (bb nil "(satisfies? clojure.core.protocols/Navigable {})")))
(is (true? (bb nil "(satisfies? clojure.core.protocols/IKVReduce {})"))))
;;;; Scratch
(comment