Liking cljdoc? Tell your friends :D

graal-spec-tools

CircleCI codecov

A Clojure library for spec-driven interop with GraalVM Polyglot runtime.

[org.clojars.zharinov/graal-spec-tools "0.1.1"]

Usage

Data interop

(require '[spec-tools.data-spec :as ds])
(require '[graal-spec-tools.core :as gst])

(def spec 
  (ds/spec
    {:name ::person
     :spec {:id                   integer?
            :boss                 boolean?
            (ds/req :name)        string?
            (ds/opt :description) string?
            :aliases              [(ds/or {:maps    {:alias string?}
                                           :strings string?})]
            :orders               [{:id          int?
                                    :description string?}]
            :languages            #{keyword?}
            :address              (ds/maybe
                                    {:street string?
                                     :zip    string?})}}))

(def value {:id          42
            :boss        true
            :name        "Liisa"
            :description "Liisa is a valid boss"
            :aliases     [{:alias "Lissu"} "Liisu"]
            :orders      [{:id 1, :description "cola"}
                          {:id 2, :description "kebab"}]
            :languages   #{:clj :cljs}
            :address     {:street "Amurinkatu 2"
                          :zip    "33210"}})

(instance? org.graalvm.polyglot.proxy.Proxy
  (gst/encode spec value))
;; => true

(def context 
  (-> (org.graalvm.polyglot.Context/newBuilder 
        (into-array String ["js"]))
    (.build)))

(let [bindings (.getBindings context "js")]
  (.putMember bindings "value" (gst/encode spec value))
  (= value
     (gst/decode spec
       (.eval context "js"
         "const x = JSON.stringify(value, null, 2)
          console.log(x)
          JSON.parse(x)"))))
;; => true

Function interop

Note: use predefined Spec records to avoid "Argument error" exceptions.

(require '[clojure.spec.alpha :as s])
(require '[spec-tools.spec :as spec])
(require '[graal-spec-tools.core :as gst])

(def args-spec
  (s/cat
    :x spec/integer?
    :y spec/string?))

(def ret-spec boolean?)

(def fn-spec
  (gst/fspec
    {:name ::sample-fn
     :args args-spec
     :ret  ret-spec}))

(def context 
  (-> (org.graalvm.polyglot.Context/newBuilder 
        (into-array String ["js"]))
    (.build)))

(let [bindings (.getBindings context "js")
      fn-clj   (fn [x y] (= (str x) y))]
  (.putMember bindings "fn" (gst/encode fn-spec fn-clj))
  (.eval context "js" "fn(42, '42')")))
;; => #graal[true]

(let [fn-graal (.eval context "js" "(x, y) => x == y")
      fn-clj   (gst/decode fn-spec fn-graal)]
  (fn-clj 42 "foo"))
;; => false

Higher-order functions should work as well.

License

Copyright © 2019 Sergei Zharinov

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

Can you improve this documentation?Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close