Skip to content

Instantly share code, notes, and snippets.

@oakmac
Created October 21, 2024 14:19
Show Gist options
  • Save oakmac/02122ae20206fe4fcc208e0ff8c35700 to your computer and use it in GitHub Desktop.
Save oakmac/02122ae20206fe4fcc208e0ff8c35700 to your computer and use it in GitHub Desktop.
Standard Clojure Style v0.10.0 on Wolframite
diff --git a/src/wolframite/api/v1.clj b/src/wolframite/api/v1.clj
index 1ba746a..f8c2754 100644
--- a/src/wolframite/api/v1.clj
+++ b/src/wolframite/api/v1.clj
@@ -1,7 +1,8 @@
(ns wolframite.api.v1
(:refer-clojure :exclude [eval])
- (:require [wolframite.core :as core]
- [wolframite.lib.helpers :as helper]))
+ (:require
+ [wolframite.core :as core]
+ [wolframite.lib.helpers :as helper]))
(def start!
"Initialize Wolframite and start! the underlying Wolfram Kernel - required once before you make any eval calls.
@@ -88,5 +89,4 @@
(comment
(start!)
(! '(+ 1 1))
- (help! '(+ 1 1)) ;; => Doesn't seem to be opening a browser for me?
- )
+ (help! '(+ 1 1))) ;; => Doesn't seem to be opening a browser for me?
diff --git a/src/wolframite/base/cep.clj b/src/wolframite/base/cep.clj
index 0877dcb..97950fa 100644
--- a/src/wolframite/base/cep.clj
+++ b/src/wolframite/base/cep.clj
@@ -1,24 +1,24 @@
-(ns wolframite.base.cep
- (:require
- [wolframite.lib.options :as options]
- [wolframite.base.convert :as convert]
- [wolframite.base.evaluate :as evaluate]
- [wolframite.base.parse :as parse]))
-
-(defn- identity-first [x & _] x)
-
-(defn cep
- "Convert-Evaluate-Parse pipeline.
- Convert: from clj data to jlink Expr
- Evaluate: the Expr on (some) Wolfram Engine
- Parse: returned result into clj data.
- Each stage can be skipped with appropriate `opts` `:flag` e.g. `:no-parse`"
- [expr {:keys [flags]
- :as opts}]
- (let [convert (if (options/flag?' flags :convert) convert/convert identity-first)
- evaluate (if (options/flag?' flags :evaluate) evaluate/evaluate identity-first)
- parse (if (options/flag?' flags :parse) parse/parse identity-first)]
- (-> expr
- (convert opts)
- (evaluate opts)
- (parse opts))))
+(ns wolframite.base.cep
+ (:require
+ [wolframite.base.convert :as convert]
+ [wolframite.base.evaluate :as evaluate]
+ [wolframite.base.parse :as parse]
+ [wolframite.lib.options :as options]))
+
+(defn- identity-first [x & _] x)
+
+(defn cep
+ "Convert-Evaluate-Parse pipeline.
+ Convert: from clj data to jlink Expr
+ Evaluate: the Expr on (some) Wolfram Engine
+ Parse: returned result into clj data.
+ Each stage can be skipped with appropriate `opts` `:flag` e.g. `:no-parse`"
+ [expr {:keys [flags]
+ :as opts}]
+ (let [convert (if (options/flag?' flags :convert) convert/convert identity-first)
+ evaluate (if (options/flag?' flags :evaluate) evaluate/evaluate identity-first)
+ parse (if (options/flag?' flags :parse) parse/parse identity-first)]
+ (-> expr
+ (convert opts)
+ (evaluate opts)
+ (parse opts))))
diff --git a/src/wolframite/base/convert.clj b/src/wolframite/base/convert.clj
index 529eb25..70b117d 100644
--- a/src/wolframite/base/convert.clj
+++ b/src/wolframite/base/convert.clj
@@ -1,178 +1,179 @@
-(ns wolframite.base.convert
- "Convert a Clojure expression into a Wolfram JLink expression"
- (:require [wolframite.impl.jlink-instance :as jlink-instance]
- [wolframite.impl.protocols :as proto]
- [wolframite.impl.wolfram-syms.intern :as intern]
- [wolframite.lib.options :as options]
- [wolframite.base.express :as express]
- [wolframite.base.expr :as expr]
- [wolframite.runtime.defaults :as defaults]))
-
-;; (remove-ns 'wolframite.base.convert)
-
-;; * defmulti and dispatch
-
-(defn- primitive?
- "Is `x` a 'primitive' value that can be directly turned into an Expr?"
- [x]
- (or (number? x)
- (string? x)))
-
-(defn- supported-primitive-array? [xs]
- ;; See jlink.Expr constructor for the types actually supported
- (some-> xs .getClass .componentType (#{Byte/TYPE Double/TYPE Integer/TYPE Long/TYPE Short/TYPE})))
-
-(defn- dispatch [obj]
- (cond (and (list? obj)
- (empty? obj)) :null
- (seq? obj) :expr
- (or (vector? obj)
- (list? obj)) :list
- (ratio? obj) :rational
- (primitive? obj) :primitive
- (map? obj) :hash-map
- (symbol? obj) :symbol
- (nil? obj) :null
- (fn? obj) :fn-obj
- :else nil))
-
-(defmulti convert
- "Convert a Wolframite clj expression into a JLink object representation"
- (fn [clj-expr _opts] (dispatch clj-expr))) ; TODO Pass jlink-instance in explicitly inst. of fetching from the global
-
-;; * Helpers
-
-(defn- simple-vector? [coll _]
- (and (sequential? coll)
- (not-any? dispatch coll)))
-
-(defn- simple-matrix? [coll opts]
- (and (sequential? coll)
- (every? #(simple-vector? % opts) coll)))
-
-(defn- cexpr-from-postfix-form [cexprs]
- (assert (sequential? cexprs))
- (loop [cexpr (first cexprs)
- remaining (rest cexprs)]
- (if (seq remaining)
- (recur (list (first remaining) cexpr) (rest remaining))
- cexpr)))
-
-(defn- cexpr-from-prefix-form [cexprs]
- (assert (sequential? cexprs))
- (cexpr-from-postfix-form (reverse cexprs)))
-
-;; * Method impls
-
-(defmethod convert nil [obj _]
- ;; A fall-back implementation, for anything we do not handle directly ourselves elsewhere here.
- ;; Also triggered for any other unknown/unhandled type, e.g. a :kwd
- (cond
- (proto/expr? (jlink-instance/get) obj)
- obj ; already a jlink Expr
-
- (supported-primitive-array? obj)
- (proto/expr (jlink-instance/get) obj)
-
- :else
- (proto/->expr (jlink-instance/get) obj)))
-
-(defmethod convert :fn-obj [obj opts]
- ;; This normally means that the expression contained a reference to a var in wolframite.wolfram,
- ;; which has not been turned into a symbol for some reason, typically b/c it was not a fn call
- ;; (those do 'symbolify' themselves) => we check and do this here
- (if-let [fn-name (intern/interned-var-val->symbol obj)]
- (convert fn-name opts)
- (throw (IllegalArgumentException.
- (str "An expression contains a function object, which is not intern/wolfram-fn => "
- "don't know how to turn it into a symbol that Wolfram could interpret: "
- obj)))))
-
-(defmethod convert :null [_ opts]
- (convert 'Null opts))
-
-(defmethod convert :rational [n opts]
- (convert (list 'Rational (.numerator n) (.denominator n)) opts))
-
-(defmethod convert :primitive [primitive _opts]
- (proto/expr (jlink-instance/get) primitive))
-
-(defn ->wolfram-str-expr
- "Turn `str` (a raw Wolfram expression string) into a value that `convert` will
- properly process as an expression, and not as a primitive string."
- [str]
- {::wolfram-str-expr str})
-
-(defn- wolfram-str-expr->jlink-expr [wolfram-str-expr-map opts]
- (do (assert (= 1 (count wolfram-str-expr-map)) "::wolfram-str-expr must stand on its own")
- (assert (-> wolfram-str-expr-map vals first string?) "::wolfram-str-expr value must be a string")
- (express/express (::wolfram-str-expr wolfram-str-expr-map) opts)))
-
-(defmethod convert :hash-map [map opts]
- ;; A map could be either normal map value the user supplied, or it could be our magical
- ;; map used to mark the actual value for special treatment, namely to be interpreted as
- ;; Wolfram code in a string; see `->wolfram-str-expr`
- (if (::wolfram-str-expr map)
- (wolfram-str-expr->jlink-expr map opts)
- (convert (apply list 'Association (for [[key value] map] (list 'Rule key value))) opts)))
-
-(defmethod convert :symbol [sym {:keys [aliases] ::keys [args] :as opts}]
- (let [all-aliases (merge defaults/all-aliases aliases)]
- (if-let [alias-sym-or-fn (all-aliases sym)]
- (if (defaults/experimental-fn-alias? alias-sym-or-fn)
- (convert (alias-sym-or-fn args) opts)
- (convert alias-sym-or-fn opts))
- ;; Numbered args of shorthand lambdas - Clojure's `#(+ %1 %2)` => Wolfs #1 and #1 = Slot[1] and Slot[2]
- (if-let [[_ ^String n] (re-matches #"%(\d*)" (str sym))]
- (let [n (Long/valueOf (if (= "" n) "1" n))]
- (convert (list 'Slot n) opts))
- ;(let [s (str-utils/replace (str sym) #"\|(.*?)\|" #(str "\\\\[" (second %) "]"))] )
- (let [s (str sym)]
- (if (re-find #"[^a-zA-Z0-9$\/]" s)
- (throw (ex-info (str "Unsupported symbol / unknown alias: Symbols passed to Mathematica must be alphanumeric"
- " (apart from forward slashes and dollar signs). Other symbols may"
- " only be used if there is defined a Wolframite alias for them."
- " Passed: " s
- " Known aliases: " (or (-> aliases keys sort seq) "N/A"))
- {:unknown-symbol s
- :known-symbols (keys aliases)}))
- (proto/expr (jlink-instance/get) :Expr/SYMBOL s)))))))
-
-(defn- convert-non-simple-list [elms opts]
- (let [converted-parts (map #(cond-> % (dispatch %) (convert opts)) elms)]
- (if (every? (partial proto/expr? (jlink-instance/get)) converted-parts)
- (proto/expr (jlink-instance/get)
- (cons (convert 'List opts)
- converted-parts))
- (convert (to-array converted-parts) opts))))
-
-(defmethod convert :list [coll opts]
- (cond (simple-matrix? coll opts) (convert (to-array-2d coll) opts)
- (simple-vector? coll opts) (convert (to-array coll) opts)
- :else (convert-non-simple-list coll opts)))
-
-(defmethod convert :expr [[head & tail :as clj-expr] opts]
- (let [macro head
- arg (first tail)]
- (cond (= 'clojure.core/deref macro) (convert (cexpr-from-prefix-form arg) opts)
- (= 'clojure.core/meta macro) (convert (cexpr-from-postfix-form arg) opts)
- (= 'var macro) (convert (list 'Function arg) opts)
- ;; convert '(whatever...)
- ;; Quoted symbol intended to be sent as Wolfram symbol
- (and (= 'quote macro)
- (symbol? arg)) (convert arg opts)
- (= 'quote macro) (throw (ex-info (str "Unsupported quoted expression:"
- (pr-str clj-expr))
- {:expr clj-expr}))
- ;; Originally we called `(express/express arg opts)` but it fails b/c it only handles strings
- :else (expr/expr-from-parts
- (cons (convert head
- (cond-> opts
- (symbol? head)
- (assoc ::args tail)))
- (doall (map #(convert % opts) tail)))))))
-
-(comment
- (convert '(whatever 1) nil)
- (convert '(- 12 1 2) {})
- (convert '(Plus 1 2) {}))
+(ns wolframite.base.convert
+ "Convert a Clojure expression into a Wolfram JLink expression"
+ (:require
+ [wolframite.base.expr :as expr]
+ [wolframite.base.express :as express]
+ [wolframite.impl.jlink-instance :as jlink-instance]
+ [wolframite.impl.protocols :as proto]
+ [wolframite.impl.wolfram-syms.intern :as intern]
+ [wolframite.lib.options :as options]
+ [wolframite.runtime.defaults :as defaults]))
+
+;; (remove-ns 'wolframite.base.convert)
+
+;; * defmulti and dispatch
+
+(defn- primitive?
+ "Is `x` a 'primitive' value that can be directly turned into an Expr?"
+ [x]
+ (or (number? x)
+ (string? x)))
+
+(defn- supported-primitive-array? [xs]
+ ;; See jlink.Expr constructor for the types actually supported
+ (some-> xs .getClass .componentType (#{Byte/TYPE Double/TYPE Integer/TYPE Long/TYPE Short/TYPE})))
+
+(defn- dispatch [obj]
+ (cond (and (list? obj)
+ (empty? obj)) :null
+ (seq? obj) :expr
+ (or (vector? obj)
+ (list? obj)) :list
+ (ratio? obj) :rational
+ (primitive? obj) :primitive
+ (map? obj) :hash-map
+ (symbol? obj) :symbol
+ (nil? obj) :null
+ (fn? obj) :fn-obj
+ :else nil))
+
+(defmulti convert
+ "Convert a Wolframite clj expression into a JLink object representation"
+ (fn [clj-expr _opts] (dispatch clj-expr))) ; TODO Pass jlink-instance in explicitly inst. of fetching from the global
+
+;; * Helpers
+
+(defn- simple-vector? [coll _]
+ (and (sequential? coll)
+ (not-any? dispatch coll)))
+
+(defn- simple-matrix? [coll opts]
+ (and (sequential? coll)
+ (every? #(simple-vector? % opts) coll)))
+
+(defn- cexpr-from-postfix-form [cexprs]
+ (assert (sequential? cexprs))
+ (loop [cexpr (first cexprs)
+ remaining (rest cexprs)]
+ (if (seq remaining)
+ (recur (list (first remaining) cexpr) (rest remaining))
+ cexpr)))
+
+(defn- cexpr-from-prefix-form [cexprs]
+ (assert (sequential? cexprs))
+ (cexpr-from-postfix-form (reverse cexprs)))
+
+;; * Method impls
+
+(defmethod convert nil [obj _]
+ ;; A fall-back implementation, for anything we do not handle directly ourselves elsewhere here.
+ ;; Also triggered for any other unknown/unhandled type, e.g. a :kwd
+ (cond
+ (proto/expr? (jlink-instance/get) obj)
+ obj ; already a jlink Expr
+
+ (supported-primitive-array? obj)
+ (proto/expr (jlink-instance/get) obj)
+
+ :else
+ (proto/->expr (jlink-instance/get) obj)))
+
+(defmethod convert :fn-obj [obj opts]
+ ;; This normally means that the expression contained a reference to a var in wolframite.wolfram,
+ ;; which has not been turned into a symbol for some reason, typically b/c it was not a fn call
+ ;; (those do 'symbolify' themselves) => we check and do this here
+ (if-let [fn-name (intern/interned-var-val->symbol obj)]
+ (convert fn-name opts)
+ (throw (IllegalArgumentException.
+ (str "An expression contains a function object, which is not intern/wolfram-fn => "
+ "don't know how to turn it into a symbol that Wolfram could interpret: "
+ obj)))))
+
+(defmethod convert :null [_ opts]
+ (convert 'Null opts))
+
+(defmethod convert :rational [n opts]
+ (convert (list 'Rational (.numerator n) (.denominator n)) opts))
+
+(defmethod convert :primitive [primitive _opts]
+ (proto/expr (jlink-instance/get) primitive))
+
+(defn ->wolfram-str-expr
+ "Turn `str` (a raw Wolfram expression string) into a value that `convert` will
+ properly process as an expression, and not as a primitive string."
+ [str]
+ {::wolfram-str-expr str})
+
+(defn- wolfram-str-expr->jlink-expr [wolfram-str-expr-map opts]
+ (do (assert (= 1 (count wolfram-str-expr-map)) "::wolfram-str-expr must stand on its own")
+ (assert (-> wolfram-str-expr-map vals first string?) "::wolfram-str-expr value must be a string")
+ (express/express (::wolfram-str-expr wolfram-str-expr-map) opts)))
+
+(defmethod convert :hash-map [map opts]
+ ;; A map could be either normal map value the user supplied, or it could be our magical
+ ;; map used to mark the actual value for special treatment, namely to be interpreted as
+ ;; Wolfram code in a string; see `->wolfram-str-expr`
+ (if (::wolfram-str-expr map)
+ (wolfram-str-expr->jlink-expr map opts)
+ (convert (apply list 'Association (for [[key value] map] (list 'Rule key value))) opts)))
+
+(defmethod convert :symbol [sym {:keys [aliases] ::keys [args] :as opts}]
+ (let [all-aliases (merge defaults/all-aliases aliases)]
+ (if-let [alias-sym-or-fn (all-aliases sym)]
+ (if (defaults/experimental-fn-alias? alias-sym-or-fn)
+ (convert (alias-sym-or-fn args) opts)
+ (convert alias-sym-or-fn opts))
+ ;; Numbered args of shorthand lambdas - Clojure's `#(+ %1 %2)` => Wolfs #1 and #1 = Slot[1] and Slot[2]
+ (if-let [[_ ^String n] (re-matches #"%(\d*)" (str sym))]
+ (let [n (Long/valueOf (if (= "" n) "1" n))]
+ (convert (list 'Slot n) opts))
+ ; (let [s (str-utils/replace (str sym) #"\|(.*?)\|" #(str "\\\\[" (second %) "]"))] )
+ (let [s (str sym)]
+ (if (re-find #"[^a-zA-Z0-9$\/]" s)
+ (throw (ex-info (str "Unsupported symbol / unknown alias: Symbols passed to Mathematica must be alphanumeric"
+ " (apart from forward slashes and dollar signs). Other symbols may"
+ " only be used if there is defined a Wolframite alias for them."
+ " Passed: " s
+ " Known aliases: " (or (-> aliases keys sort seq) "N/A"))
+ {:unknown-symbol s
+ :known-symbols (keys aliases)}))
+ (proto/expr (jlink-instance/get) :Expr/SYMBOL s)))))))
+
+(defn- convert-non-simple-list [elms opts]
+ (let [converted-parts (map #(cond-> % (dispatch %) (convert opts)) elms)]
+ (if (every? (partial proto/expr? (jlink-instance/get)) converted-parts)
+ (proto/expr (jlink-instance/get)
+ (cons (convert 'List opts)
+ converted-parts))
+ (convert (to-array converted-parts) opts))))
+
+(defmethod convert :list [coll opts]
+ (cond (simple-matrix? coll opts) (convert (to-array-2d coll) opts)
+ (simple-vector? coll opts) (convert (to-array coll) opts)
+ :else (convert-non-simple-list coll opts)))
+
+(defmethod convert :expr [[head & tail :as clj-expr] opts]
+ (let [macro head
+ arg (first tail)]
+ (cond (= 'clojure.core/deref macro) (convert (cexpr-from-prefix-form arg) opts)
+ (= 'clojure.core/meta macro) (convert (cexpr-from-postfix-form arg) opts)
+ (= 'var macro) (convert (list 'Function arg) opts)
+ ;; convert '(whatever...)
+ ;; Quoted symbol intended to be sent as Wolfram symbol
+ (and (= 'quote macro)
+ (symbol? arg)) (convert arg opts)
+ (= 'quote macro) (throw (ex-info (str "Unsupported quoted expression:"
+ (pr-str clj-expr))
+ {:expr clj-expr}))
+ ;; Originally we called `(express/express arg opts)` but it fails b/c it only handles strings
+ :else (expr/expr-from-parts
+ (cons (convert head
+ (cond-> opts
+ (symbol? head)
+ (assoc ::args tail)))
+ (doall (map #(convert % opts) tail)))))))
+
+(comment
+ (convert '(whatever 1) nil)
+ (convert '(- 12 1 2) {})
+ (convert '(Plus 1 2) {}))
diff --git a/src/wolframite/base/evaluate.clj b/src/wolframite/base/evaluate.clj
index 9d75a4b..4cd3fee 100644
--- a/src/wolframite/base/evaluate.clj
+++ b/src/wolframite/base/evaluate.clj
@@ -1,58 +1,59 @@
-(ns wolframite.base.evaluate
- "The core of evaluation: send a converted JLink expression to a Wolfram Kernel for evaluation and return the result."
- (:require [wolframite.impl.protocols :as proto]
- [wolframite.lib.options :as options]
- [wolframite.base.convert :as convert]))
-
-(declare evaluate)
-
-(defn process-state [pid-expr {:keys [flags] :as opts}]
- (assert (options/flag?' flags :serial))
- (let [state-expr (evaluate (convert/convert (list 'ProcessState pid-expr) opts) opts)
- state-prefix (first (.toString state-expr))]
- (cond (= \r state-prefix) [:running nil]
- (= \f state-prefix) [:finished (.part state-expr 1)]
- (= \q state-prefix) [:queued nil]
- :else
- (throw (Exception. (str "Error! State unrecognized: " state-expr))))))
-
-(defn queue-run-or-wait [{:keys [flags config] :as opts}]
- (assert (options/flag?' flags :serial))
- (let [lqr-atom (atom nil)
- lqr-time @lqr-atom
- nano-pi (* 1000000 (:poll-interval config))
- run-in (when lqr-time (- (+ lqr-time nano-pi) (System/nanoTime)))]
- (if (or (nil? run-in) (neg? run-in))
- (do
- ;; TODO: add debug logging "QueueRunning at time"
- (evaluate (convert/convert '(QueueRun) opts) opts)
- (swap! lqr-atom (fn [_] (System/nanoTime))))
- ;; TODO: else branch: add debug logging "Sleeping for"
- (Thread/sleep ^long (quot run-in 1000000)))))
-
-(defn evaluate [expr {:keys [jlink-instance]
- :as opts}]
- {:pre [jlink-instance]}
- (assert (proto/expr? jlink-instance expr))
-
- (if (options/flag?' (:flags opts) :serial)
- (proto/evaluate! jlink-instance expr)
- (let [opts' (update opts :flags conj :serial) ;; FIXME: make sure this is supposed to be `:serial`, it's what I gather from previous version of the code
- ;; Generate a new, unique symbol for a ref to the submitted computation (~ Java Future?)
- pid-expr (evaluate (convert/convert
- (list 'Unique
- ; Beware: technically, this is an invalid clj symbol due to the slashes:
- (symbol "Wolframite/Concurrent/process")) opts')
- opts)]
- ;; Submit the expr for evaluation on the next available parallel kernel
- (evaluate (convert/convert (list '= pid-expr (list 'ParallelSubmit expr)) opts') opts)
- (evaluate (convert/convert '(QueueRun) opts') opts)
- (loop []
- (let [[state result] (process-state pid-expr opts)]
- (if (not= :finished state)
- (do
- (queue-run-or-wait opts)
- (recur))
- (do
- (evaluate (convert/convert (list 'Remove pid-expr) opts') opts)
- result)))))))
+(ns wolframite.base.evaluate
+ "The core of evaluation: send a converted JLink expression to a Wolfram Kernel for evaluation and return the result."
+ (:require
+ [wolframite.base.convert :as convert]
+ [wolframite.impl.protocols :as proto]
+ [wolframite.lib.options :as options]))
+
+(declare evaluate)
+
+(defn process-state [pid-expr {:keys [flags] :as opts}]
+ (assert (options/flag?' flags :serial))
+ (let [state-expr (evaluate (convert/convert (list 'ProcessState pid-expr) opts) opts)
+ state-prefix (first (.toString state-expr))]
+ (cond (= \r state-prefix) [:running nil]
+ (= \f state-prefix) [:finished (.part state-expr 1)]
+ (= \q state-prefix) [:queued nil]
+ :else
+ (throw (Exception. (str "Error! State unrecognized: " state-expr))))))
+
+(defn queue-run-or-wait [{:keys [flags config] :as opts}]
+ (assert (options/flag?' flags :serial))
+ (let [lqr-atom (atom nil)
+ lqr-time @lqr-atom
+ nano-pi (* 1000000 (:poll-interval config))
+ run-in (when lqr-time (- (+ lqr-time nano-pi) (System/nanoTime)))]
+ (if (or (nil? run-in) (neg? run-in))
+ (do
+ ;; TODO: add debug logging "QueueRunning at time"
+ (evaluate (convert/convert '(QueueRun) opts) opts)
+ (swap! lqr-atom (fn [_] (System/nanoTime))))
+ ;; TODO: else branch: add debug logging "Sleeping for"
+ (Thread/sleep ^long (quot run-in 1000000)))))
+
+(defn evaluate [expr {:keys [jlink-instance]
+ :as opts}]
+ {:pre [jlink-instance]}
+ (assert (proto/expr? jlink-instance expr))
+
+ (if (options/flag?' (:flags opts) :serial)
+ (proto/evaluate! jlink-instance expr)
+ (let [opts' (update opts :flags conj :serial) ;; FIXME: make sure this is supposed to be `:serial`, it's what I gather from previous version of the code
+ ;; Generate a new, unique symbol for a ref to the submitted computation (~ Java Future?)
+ pid-expr (evaluate (convert/convert
+ (list 'Unique
+ ; Beware: technically, this is an invalid clj symbol due to the slashes:
+ (symbol "Wolframite/Concurrent/process")) opts')
+ opts)]
+ ;; Submit the expr for evaluation on the next available parallel kernel
+ (evaluate (convert/convert (list '= pid-expr (list 'ParallelSubmit expr)) opts') opts)
+ (evaluate (convert/convert '(QueueRun) opts') opts)
+ (loop []
+ (let [[state result] (process-state pid-expr opts)]
+ (if (not= :finished state)
+ (do
+ (queue-run-or-wait opts)
+ (recur))
+ (do
+ (evaluate (convert/convert (list 'Remove pid-expr) opts') opts)
+ result)))))))
diff --git a/src/wolframite/base/expr.clj b/src/wolframite/base/expr.clj
index 4e0badf..3a33916 100644
--- a/src/wolframite/base/expr.clj
+++ b/src/wolframite/base/expr.clj
@@ -1,17 +1,16 @@
-(ns wolframite.base.expr
- (:require [wolframite.impl.jlink-instance :as jlink-instance]
- [wolframite.impl.protocols :as proto]))
-
-(defn head-str [expr]
- (assert (proto/expr? (jlink-instance/get) expr))
- (.toString (.head expr)))
-
-(defn parts [expr]
- (assert (proto/expr? (jlink-instance/get) expr))
- (cons (.head expr) (seq (.args expr))))
-
-(defn expr-from-parts [expr-coll]
- (assert (every? #(proto/expr? (jlink-instance/get) %) expr-coll))
- (proto/expr (jlink-instance/get) expr-coll))
-
-
+(ns wolframite.base.expr
+ (:require
+ [wolframite.impl.jlink-instance :as jlink-instance]
+ [wolframite.impl.protocols :as proto]))
+
+(defn head-str [expr]
+ (assert (proto/expr? (jlink-instance/get) expr))
+ (.toString (.head expr)))
+
+(defn parts [expr]
+ (assert (proto/expr? (jlink-instance/get) expr))
+ (cons (.head expr) (seq (.args expr))))
+
+(defn expr-from-parts [expr-coll]
+ (assert (every? #(proto/expr? (jlink-instance/get) %) expr-coll))
+ (proto/expr (jlink-instance/get) expr-coll))
diff --git a/src/wolframite/base/express.clj b/src/wolframite/base/express.clj
index 39d6218..7fde297 100644
--- a/src/wolframite/base/express.clj
+++ b/src/wolframite/base/express.clj
@@ -1,24 +1,25 @@
-(ns wolframite.base.express
- (:require [wolframite.impl.protocols :as proto]))
-
-(defn express
- "??? Convert a _string_ expression into JLink.Expr using Wolfram itself"
- [s {:keys [jlink-instance]}]
- {:pre [jlink-instance]}
- (assert (string? s) (str "Expected '" (pr-str s) "' to be a string but is " (type s)))
- ;; TODO: debug log: "express string>"
- (let [held-s (str "HoldComplete[" s "]")
- link (or (proto/kernel-link jlink-instance)
- (throw (IllegalStateException.
- (str "Something is wrong - there is no JLink instance, which shouldn't"
- " be possible. Try to stop and start Wolframite again."))))
- output (io!
- (locking link
- (doto link
- (.evaluate held-s)
- (.waitForAnswer))
- (.. link getExpr args)))] ; TODO (jakub) get rid of reflection, move into the protocol
- (if (= (count output) 1)
- (first output)
- (throw (Exception. (format "Invalid expression `%s`. Output lenght expected 1, was %d"
- s (count output)))))))
\ No newline at end of file
+(ns wolframite.base.express
+ (:require
+ [wolframite.impl.protocols :as proto]))
+
+(defn express
+ "??? Convert a _string_ expression into JLink.Expr using Wolfram itself"
+ [s {:keys [jlink-instance]}]
+ {:pre [jlink-instance]}
+ (assert (string? s) (str "Expected '" (pr-str s) "' to be a string but is " (type s)))
+ ;; TODO: debug log: "express string>"
+ (let [held-s (str "HoldComplete[" s "]")
+ link (or (proto/kernel-link jlink-instance)
+ (throw (IllegalStateException.
+ (str "Something is wrong - there is no JLink instance, which shouldn't"
+ " be possible. Try to stop and start Wolframite again."))))
+ output (io!
+ (locking link
+ (doto link
+ (.evaluate held-s)
+ (.waitForAnswer))
+ (.. link getExpr args)))] ; TODO (jakub) get rid of reflection, move into the protocol
+ (if (= (count output) 1)
+ (first output)
+ (throw (Exception. (format "Invalid expression `%s`. Output lenght expected 1, was %d"
+ s (count output)))))))
diff --git a/src/wolframite/base/package.clj b/src/wolframite/base/package.clj
index 3fafe18..a35f1cf 100644
--- a/src/wolframite/base/package.clj
+++ b/src/wolframite/base/package.clj
@@ -37,7 +37,7 @@
- `alias` - Clojure symbol to be used for accessing the Wolfram context. This will effectively become a Clojure namespace
See [[intern-context!]] for details of turning the Wolfram context into a Clojure namespace."
-;; TODO: Should check that the symbol isn't already being used.
+ ;; TODO: Should check that the symbol isn't already being used.
([wl-eval path]
(let [context (-> path fs/file-name fs/strip-ext)]
(load! wl-eval path context (symbol context))))
@@ -55,4 +55,4 @@ See [[intern-context!]] for details of turning the Wolfram context into a Clojur
(comment
(load! wolframite.core/eval "/tmp/fake.wl")
- (load! wolframite.core/eval "./resources/WolframPackageDemo.wl"))
\ No newline at end of file
+ (load! wolframite.core/eval "./resources/WolframPackageDemo.wl"))
diff --git a/src/wolframite/base/parse.clj b/src/wolframite/base/parse.clj
index fe444e9..ae8249f 100644
--- a/src/wolframite/base/parse.clj
+++ b/src/wolframite/base/parse.clj
@@ -1,202 +1,202 @@
-(ns wolframite.base.parse
- "Translate a jlink.Expr returned from an evaluation into Clojure data"
- (:require
- [clojure.set :as set]
- [wolframite.impl.jlink-instance :as jlink-instance]
- [wolframite.impl.protocols :as proto]
- [wolframite.lib.options :as options]
- [wolframite.base.expr :as expr]
- [clojure.string :as str]))
-
-(declare parse)
-
-(defn pascal->kebab
- [s]
- (some-> s
- (str/replace #"\w(\p{Upper})" (fn [[[p l] _]] (str p "-" (str/lower-case l))))
- str/lower-case))
-
-(defn entity-type->keyword [expr opts]
- (let [head (pascal->kebab (expr/head-str expr))
- parts (reduce (fn [acc part]
- (into acc (cond
- (string? part) [(pascal->kebab part)]
- (coll? part) (reverse (map pascal->kebab part))
- :else nil)))
- [head]
- (map #(parse % opts) (.args expr)))]
- ;; BAIL: if any of the parts are not recognized,
- ;; let it go through normal parsing
- (when (not-any? nil? parts)
- (keyword (str/join "." (butlast parts))
- (last parts)))))
-
-(defn custom-parse-dispatch [expr _opts]
- (let [head (symbol (expr/head-str expr))]
- head))
-
-(defn atom? [expr]
- (not (.listQ expr)))
-
-(defn simple-vector-type [expr]
- (proto/expr-element-type (jlink-instance/get) :vector expr))
-
-(defn simple-matrix-type [expr]
- (proto/expr-element-type (jlink-instance/get) :matrix expr))
-
-(defn simple-array-type [expr]
- (or (simple-vector-type expr) (simple-matrix-type expr)))
-
-;; FIXME: change name (it's more of a concrete type map)
-(defn bound-map [f coll {:keys [flags] :as opts}]
- (if (options/flag?' flags :vectors)
- (mapv #(f % opts) coll)
- (map #(f % opts) coll)))
-
-(defn parse-complex-list [expr opts]
- (bound-map parse (.args expr) opts))
-
-(defn parse-integer [expr]
- (let [i (.asLong expr)]
- (if (and (<= i Integer/MAX_VALUE)
- (>= i Integer/MIN_VALUE))
- (int i)
- (long i))))
-
-(defn parse-rational [expr]
- (let [numer (parse-integer (.part expr 1))
- denom (parse-integer (.part expr 2))]
- (/ numer denom)))
-
-(defn parse-symbol [expr {:keys [aliases/base-list]}]
- (let [alias->wolf (options/aliases base-list)
- smart-aliases (keep (fn [[alias wolf]]
- (when (fn? wolf) alias))
- alias->wolf)
- wolf->smart-alias (into {} (for [[alias smart-fn] (select-keys alias->wolf smart-aliases)
- wolf-sym (-> smart-fn meta :wolframite.alias/targets)
- :when wolf-sym]
- [wolf-sym alias]))
- wolf->alias (-> (apply dissoc alias->wolf smart-aliases)
- set/map-invert
- (merge wolf->smart-alias))
- s (.toString expr)
- sym (symbol (apply str (replace {\` \/} s)))]
- (if-let [alias (get wolf->alias sym)]
- alias
- (cond (= "True" s) true
- (= "False" s) false
- (= "Null" s) nil
- :else sym))))
-
-(defn parse-hash-map [expr opts]
- (let [inside (first (.args expr))
- ;; inside (first (.args expr))
- all-rules? (every? true? (map #(= "Rule" (expr/head-str %)) (.args expr)))
- rules (cond (some-> inside (.listQ)) (parse inside opts)
- all-rules? (into {}
- (map (fn [kv]
- (bound-map (fn [x _opts] (parse x opts)) kv opts))
- (.args expr)))
- (= "Dispatch" (expr/head-str inside)) (parse (first (.args inside)) opts)
- :else (assert (or (.listQ inside)
- (= "Dispatch" (expr/head-str inside)))))
- keys (map second rules)
- vals (map (comp second #(nth % 2)) rules)]
- (if (map? rules)
- rules
- (zipmap keys vals))))
-
-(defn parse-simple-atom [expr type opts]
- (cond (= type :Expr/BIGINTEGER) (.asBigInteger expr)
- (= type :Expr/BIGDECIMAL) (.asBigDecimal expr)
- (= type :Expr/INTEGER) (parse-integer expr)
- (= type :Expr/REAL) (.asDouble expr)
- (= type :Expr/STRING) (.asString expr)
- (= type :Expr/RATIONAL) (parse-rational expr)
- (= type :Expr/SYMBOL) (parse-symbol expr opts)))
-
-;; parameters list used to be: [expr & [type]] (??)
-(defn parse-simple-vector [expr type {:keys [flags] :as opts}]
- (let [type (or type (simple-vector-type expr))]
- (if (and (options/flag?' flags :N)
- (some #{:Expr/INTEGER :Expr/BIGINTEGER :Expr/REAL :Expr/BIGDECIMAL} #{type}))
- ((if (options/flag?' flags :vectors) vec seq)
- (.asArray expr (proto/->expr-type (jlink-instance/get) :Expr/REAL) 1))
- (bound-map (fn [e _opts] (parse-simple-atom e type opts)) (.args expr) opts))))
-
-(defn parse-simple-matrix [expr type opts]
- (let [type (or type (simple-matrix-type expr))]
- (bound-map (fn process-bound-map [a _opts]
- (parse-simple-vector a type opts))
- (.args expr)
- opts)))
-
-(defn parse-fn
- "Return a function that invokes the Wolfram expression `expr` (typically just a symbol naming a fn),
- converting any arguments given to it from Clojure to Wolfram and does the opposite conversion on the
- result.
- Ex.: `((parse/parse-fn 'Plus {:jlink-instance (jlink-instance/get)}) 1 2) ; => 3`
-
- Beware: Nesting such fns would result in multiple calls to Wolfram, which is inefficient. Prefer wl/eval in such cases."
- [expr opts]
- (fn [& args]
- (let [cep-fn (requiring-resolve `wolframite.base.cep/cep)]
- (cep-fn (apply list expr args) opts #_(update opts :flags #(options/set-flag % :as-expression))))))
-
-(defn parse-generic-expression [expr opts]
- (-> (list) ;must start with a real list because the promise is that expressions will be converted to lists
- (into (map #(parse % opts) (rseq (vec (.args expr)))))
- (conj (parse (.head expr) opts))))
-
-(defn parse-complex-atom [expr {:keys [flags] :as opts}]
- (let [head (expr/head-str expr)]
- (cond (.bigIntegerQ expr) (.asBigInteger expr)
- (.bigDecimalQ expr) (.asBigDecimal expr)
- (.integerQ expr) (parse-integer expr)
- (.realQ expr) (.asDouble expr)
- (.stringQ expr) (.asString expr)
- (.rationalQ expr) (parse-rational expr)
- (.symbolQ expr) (parse-symbol expr opts)
- (= "Association" head) (parse-hash-map expr opts) #_(parse-generic-expression expr opts)
- (= "Function" head) (parse-generic-expression expr opts)
- ;(if (and (options/flag?' flags :functions)
- ; (not (options/flag?' flags :full-form)))
- ; (parse-fn expr opts)
- ; (parse-generic-expression expr opts))
- :else (parse-generic-expression expr opts))))
-
-(defn standard-parse [expr {:keys [flags] :as opts}]
- (assert (proto/expr? (jlink-instance/get) expr))
- (cond
- ;(options/flag?' flags :as-function) (parse-fn expr opts)
- (or (atom? expr) (options/flag?' flags :full-form)) (parse-complex-atom expr opts)
- (simple-vector-type expr) (parse-simple-vector expr nil opts)
- (simple-matrix-type expr) (parse-simple-matrix expr nil opts)
- :else (parse-complex-list expr opts)))
-
-(ns-unmap *ns* 'custom-parse)
-(defmulti custom-parse
- "Modify how Wolfram response is parsed into Clojure data.
-
- The dispatch-val should be a symbol, matched against the first one of the result list.
-
- Example:
-
- ```clj
- ; return a Java URL from a Hyperlink call, instead of `'(Hyperlink <label> <url string>)`
- (defmethod custom-parse 'Hyperlink [expr opts]
- (-> (second (.args expr)) ; 1st = label
- (parse/parse opts)
- java.net.URI.))
-
- (wl/eval '(Hyperlink \"foo\" \"https://www.google.com\"))
- ; => #object[java.net.URI 0x3f5e5a46 \"https://www.google.com\"]
- ```"
- #'custom-parse-dispatch)
-
-(defmethod custom-parse :default [expr opts]
- (standard-parse expr opts))
-
-(defn parse [expr opts]
- (custom-parse expr opts))
+(ns wolframite.base.parse
+ "Translate a jlink.Expr returned from an evaluation into Clojure data"
+ (:require
+ [clojure.set :as set]
+ [clojure.string :as str]
+ [wolframite.base.expr :as expr]
+ [wolframite.impl.jlink-instance :as jlink-instance]
+ [wolframite.impl.protocols :as proto]
+ [wolframite.lib.options :as options]))
+
+(declare parse)
+
+(defn pascal->kebab
+ [s]
+ (some-> s
+ (str/replace #"\w(\p{Upper})" (fn [[[p l] _]] (str p "-" (str/lower-case l))))
+ str/lower-case))
+
+(defn entity-type->keyword [expr opts]
+ (let [head (pascal->kebab (expr/head-str expr))
+ parts (reduce (fn [acc part]
+ (into acc (cond
+ (string? part) [(pascal->kebab part)]
+ (coll? part) (reverse (map pascal->kebab part))
+ :else nil)))
+ [head]
+ (map #(parse % opts) (.args expr)))]
+ ;; BAIL: if any of the parts are not recognized,
+ ;; let it go through normal parsing
+ (when (not-any? nil? parts)
+ (keyword (str/join "." (butlast parts))
+ (last parts)))))
+
+(defn custom-parse-dispatch [expr _opts]
+ (let [head (symbol (expr/head-str expr))]
+ head))
+
+(defn atom? [expr]
+ (not (.listQ expr)))
+
+(defn simple-vector-type [expr]
+ (proto/expr-element-type (jlink-instance/get) :vector expr))
+
+(defn simple-matrix-type [expr]
+ (proto/expr-element-type (jlink-instance/get) :matrix expr))
+
+(defn simple-array-type [expr]
+ (or (simple-vector-type expr) (simple-matrix-type expr)))
+
+;; FIXME: change name (it's more of a concrete type map)
+(defn bound-map [f coll {:keys [flags] :as opts}]
+ (if (options/flag?' flags :vectors)
+ (mapv #(f % opts) coll)
+ (map #(f % opts) coll)))
+
+(defn parse-complex-list [expr opts]
+ (bound-map parse (.args expr) opts))
+
+(defn parse-integer [expr]
+ (let [i (.asLong expr)]
+ (if (and (<= i Integer/MAX_VALUE)
+ (>= i Integer/MIN_VALUE))
+ (int i)
+ (long i))))
+
+(defn parse-rational [expr]
+ (let [numer (parse-integer (.part expr 1))
+ denom (parse-integer (.part expr 2))]
+ (/ numer denom)))
+
+(defn parse-symbol [expr {:keys [aliases/base-list]}]
+ (let [alias->wolf (options/aliases base-list)
+ smart-aliases (keep (fn [[alias wolf]]
+ (when (fn? wolf) alias))
+ alias->wolf)
+ wolf->smart-alias (into {} (for [[alias smart-fn] (select-keys alias->wolf smart-aliases)
+ wolf-sym (-> smart-fn meta :wolframite.alias/targets)
+ :when wolf-sym]
+ [wolf-sym alias]))
+ wolf->alias (-> (apply dissoc alias->wolf smart-aliases)
+ set/map-invert
+ (merge wolf->smart-alias))
+ s (.toString expr)
+ sym (symbol (apply str (replace {\` \/} s)))]
+ (if-let [alias (get wolf->alias sym)]
+ alias
+ (cond (= "True" s) true
+ (= "False" s) false
+ (= "Null" s) nil
+ :else sym))))
+
+(defn parse-hash-map [expr opts]
+ (let [inside (first (.args expr))
+ ;; inside (first (.args expr))
+ all-rules? (every? true? (map #(= "Rule" (expr/head-str %)) (.args expr)))
+ rules (cond (some-> inside (.listQ)) (parse inside opts)
+ all-rules? (into {}
+ (map (fn [kv]
+ (bound-map (fn [x _opts] (parse x opts)) kv opts))
+ (.args expr)))
+ (= "Dispatch" (expr/head-str inside)) (parse (first (.args inside)) opts)
+ :else (assert (or (.listQ inside)
+ (= "Dispatch" (expr/head-str inside)))))
+ keys (map second rules)
+ vals (map (comp second #(nth % 2)) rules)]
+ (if (map? rules)
+ rules
+ (zipmap keys vals))))
+
+(defn parse-simple-atom [expr type opts]
+ (cond (= type :Expr/BIGINTEGER) (.asBigInteger expr)
+ (= type :Expr/BIGDECIMAL) (.asBigDecimal expr)
+ (= type :Expr/INTEGER) (parse-integer expr)
+ (= type :Expr/REAL) (.asDouble expr)
+ (= type :Expr/STRING) (.asString expr)
+ (= type :Expr/RATIONAL) (parse-rational expr)
+ (= type :Expr/SYMBOL) (parse-symbol expr opts)))
+
+;; parameters list used to be: [expr & [type]] (??)
+(defn parse-simple-vector [expr type {:keys [flags] :as opts}]
+ (let [type (or type (simple-vector-type expr))]
+ (if (and (options/flag?' flags :N)
+ (some #{:Expr/INTEGER :Expr/BIGINTEGER :Expr/REAL :Expr/BIGDECIMAL} #{type}))
+ ((if (options/flag?' flags :vectors) vec seq)
+ (.asArray expr (proto/->expr-type (jlink-instance/get) :Expr/REAL) 1))
+ (bound-map (fn [e _opts] (parse-simple-atom e type opts)) (.args expr) opts))))
+
+(defn parse-simple-matrix [expr type opts]
+ (let [type (or type (simple-matrix-type expr))]
+ (bound-map (fn process-bound-map [a _opts]
+ (parse-simple-vector a type opts))
+ (.args expr)
+ opts)))
+
+(defn parse-fn
+ "Return a function that invokes the Wolfram expression `expr` (typically just a symbol naming a fn),
+ converting any arguments given to it from Clojure to Wolfram and does the opposite conversion on the
+ result.
+ Ex.: `((parse/parse-fn 'Plus {:jlink-instance (jlink-instance/get)}) 1 2) ; => 3`
+
+ Beware: Nesting such fns would result in multiple calls to Wolfram, which is inefficient. Prefer wl/eval in such cases."
+ [expr opts]
+ (fn [& args]
+ (let [cep-fn (requiring-resolve `wolframite.base.cep/cep)]
+ (cep-fn (apply list expr args) opts #_(update opts :flags #(options/set-flag % :as-expression))))))
+
+(defn parse-generic-expression [expr opts]
+ (-> (list) ; must start with a real list because the promise is that expressions will be converted to lists
+ (into (map #(parse % opts) (rseq (vec (.args expr)))))
+ (conj (parse (.head expr) opts))))
+
+(defn parse-complex-atom [expr {:keys [flags] :as opts}]
+ (let [head (expr/head-str expr)]
+ (cond (.bigIntegerQ expr) (.asBigInteger expr)
+ (.bigDecimalQ expr) (.asBigDecimal expr)
+ (.integerQ expr) (parse-integer expr)
+ (.realQ expr) (.asDouble expr)
+ (.stringQ expr) (.asString expr)
+ (.rationalQ expr) (parse-rational expr)
+ (.symbolQ expr) (parse-symbol expr opts)
+ (= "Association" head) (parse-hash-map expr opts) #_(parse-generic-expression expr opts)
+ (= "Function" head) (parse-generic-expression expr opts)
+ ; (if (and (options/flag?' flags :functions)
+ ; (not (options/flag?' flags :full-form)))
+ ; (parse-fn expr opts)
+ ; (parse-generic-expression expr opts))
+ :else (parse-generic-expression expr opts))))
+
+(defn standard-parse [expr {:keys [flags] :as opts}]
+ (assert (proto/expr? (jlink-instance/get) expr))
+ (cond
+ ; (options/flag?' flags :as-function) (parse-fn expr opts)
+ (or (atom? expr) (options/flag?' flags :full-form)) (parse-complex-atom expr opts)
+ (simple-vector-type expr) (parse-simple-vector expr nil opts)
+ (simple-matrix-type expr) (parse-simple-matrix expr nil opts)
+ :else (parse-complex-list expr opts)))
+
+(ns-unmap *ns* 'custom-parse)
+(defmulti custom-parse
+ "Modify how Wolfram response is parsed into Clojure data.
+
+ The dispatch-val should be a symbol, matched against the first one of the result list.
+
+ Example:
+
+ ```clj
+ ; return a Java URL from a Hyperlink call, instead of `'(Hyperlink <label> <url string>)`
+ (defmethod custom-parse 'Hyperlink [expr opts]
+ (-> (second (.args expr)) ; 1st = label
+ (parse/parse opts)
+ java.net.URI.))
+
+ (wl/eval '(Hyperlink \"foo\" \"https://www.google.com\"))
+ ; => #object[java.net.URI 0x3f5e5a46 \"https://www.google.com\"]
+ ```"
+ #'custom-parse-dispatch)
+
+(defmethod custom-parse :default [expr opts]
+ (standard-parse expr opts))
+
+(defn parse [expr opts]
+ (custom-parse expr opts))
diff --git a/src/wolframite/core.clj b/src/wolframite/core.clj
index 0cc3e77..22ebd1a 100644
--- a/src/wolframite/core.clj
+++ b/src/wolframite/core.clj
@@ -32,21 +32,21 @@
"
(:refer-clojure :exclude [eval])
(:require
- [babashka.fs :as fs]
- [clojure.set :as set]
- [clojure.tools.logging :as log]
- [wolframite.base.cep :as cep]
- [wolframite.base.convert :as convert]
- [wolframite.base.evaluate :as evaluate]
- [wolframite.base.express :as express]
- [wolframite.base.package :as package]
- [wolframite.base.parse :as parse]
- [wolframite.impl.jlink-instance :as jlink-instance]
- [wolframite.impl.protocols :as proto]
- [wolframite.runtime.defaults :as defaults]
- [wolframite.runtime.jlink :as jlink]
- [wolframite.runtime.system :as system]
- [wolframite.wolfram :as w]))
+ [babashka.fs :as fs]
+ [clojure.set :as set]
+ [clojure.tools.logging :as log]
+ [wolframite.base.cep :as cep]
+ [wolframite.base.convert :as convert]
+ [wolframite.base.evaluate :as evaluate]
+ [wolframite.base.express :as express]
+ [wolframite.base.package :as package]
+ [wolframite.base.parse :as parse]
+ [wolframite.impl.jlink-instance :as jlink-instance]
+ [wolframite.impl.protocols :as proto]
+ [wolframite.runtime.defaults :as defaults]
+ [wolframite.runtime.jlink :as jlink]
+ [wolframite.runtime.system :as system]
+ [wolframite.wolfram :as w]))
(defonce ^{:deprecated true, :private true} kernel-link-atom (atom nil)) ; FIXME (jakub) DEPRECATED, access it via the jlink-instance instead
@@ -113,10 +113,10 @@
Requires [[start!]] to be called first."
[]
(zipmap
- [:wolfram-version :wolfram-kernel-name :max-license-processes]
- (eval '[$VersionNumber
- (SystemInformation "Kernel", "ProductKernelName")
- (SystemInformation "Kernel", "MaxLicenseProcesses")])))
+ [:wolfram-version :wolfram-kernel-name :max-license-processes]
+ (eval '[$VersionNumber
+ (SystemInformation "Kernel", "ProductKernelName")
+ (SystemInformation "Kernel", "MaxLicenseProcesses")])))
(defn start!
"Initialize Wolframite and start! the underlying Wolfram Kernel - required once before you make any eval calls.
@@ -247,7 +247,7 @@
- `alias` - Clojure symbol to be used for accessing the Wolfram context. This will effectively become a Clojure namespace
See `package/intern-context!` for details of turning the Wolfram context into a Clojure namespace."
-;; TODO: Should check that the symbol isn't already being used.
+ ;; TODO: Should check that the symbol isn't already being used.
([path]
(let [context (-> path fs/file-name fs/strip-ext)]
(package/load! eval path context (symbol context))))
diff --git a/src/wolframite/impl/jlink_instance.clj b/src/wolframite/impl/jlink_instance.clj
index c950391..89341db 100644
--- a/src/wolframite/impl/jlink_instance.clj
+++ b/src/wolframite/impl/jlink_instance.clj
@@ -1,7 +1,9 @@
(ns wolframite.impl.jlink-instance
- (:require [wolframite.impl.protocols :as proto])
- (:import [wolframite.impl.protocols JLink])
- (:refer-clojure :exclude [get reset!]))
+ (:refer-clojure :exclude [get reset!])
+ (:require
+ [wolframite.impl.protocols :as proto])
+ (:import
+ (wolframite.impl.protocols JLink)))
;; The actual impl. of the JLink interface, set at runtime
(defonce jlink-instance (atom nil))
diff --git a/src/wolframite/impl/jlink_proto_impl.clj b/src/wolframite/impl/jlink_proto_impl.clj
index a0457fc..f83a299 100644
--- a/src/wolframite/impl/jlink_proto_impl.clj
+++ b/src/wolframite/impl/jlink_proto_impl.clj
@@ -1,11 +1,12 @@
(ns wolframite.impl.jlink-proto-impl
"The 'real' implementation of JLink, which does depend on JLink classes and thus
cannot be loaded/required until JLink is on the classpath."
- (:require [clojure.tools.logging :as log]
- [wolframite.impl.protocols :as proto])
- (:import (clojure.lang BigInt)
- [com.wolfram.jlink Expr KernelLink MathCanvas MathLink MathLinkException MathLinkFactory
- PacketListener PacketArrivedEvent PacketPrinter]))
+ (:require
+ [clojure.tools.logging :as log]
+ [wolframite.impl.protocols :as proto])
+ (:import
+ (clojure.lang BigInt)
+ (com.wolfram.jlink Expr KernelLink MathCanvas MathLink MathLinkException MathLinkFactory PacketArrivedEvent PacketListener PacketPrinter)))
(defn- array? [x]
(some-> x class .isArray))
@@ -15,8 +16,8 @@
(cond
(sequential? primitive-or-exprs)
(Expr.
- ^Expr (first primitive-or-exprs)
- ^"[Lcom.wolfram.jlink.Expr;" (into-array Expr (rest primitive-or-exprs)))
+ ^Expr (first primitive-or-exprs)
+ ^"[Lcom.wolfram.jlink.Expr;" (into-array Expr (rest primitive-or-exprs)))
;; Here, primitive-or-exprs could be an int, a String, long[], or similar
(array? primitive-or-exprs)
@@ -69,7 +70,7 @@
(let [expr (.getExpr link)]
(when-not (.symbolQ expr)
;; not sure why these are sent, not useful; e.g. Get when a Get call failed etc.
- {:type :message :content expr}))
+ {:type :message :content expr}))
nil)
(swap! capture conj)))
@@ -77,7 +78,7 @@
(comment
(let [link (proto/kernel-link ((requiring-resolve 'wolframite.impl.jlink-instance/get)))]
- ;(.removePacketListener link packet-listener)
+ ; (.removePacketListener link packet-listener)
(.addPacketListener link packet-listener)
,)
,)
@@ -153,7 +154,7 @@
;; Note: The call below ensures we actually try to connect to the kernel
(.discardAnswer))
(reset! kernel-link-atom))]
- ;(.getError kernel-link) (.getErrorMessage kernel-link)
+ ; (.getError kernel-link) (.getErrorMessage kernel-link)
kernel-link)
(catch MathLinkException e
(if (= (ex-message e) "MathLink connection was lost.")
@@ -193,9 +194,9 @@
^String (apply str (replace {\/ \`} name))))
(->expr [_this obj] ; fallback for transforming anything we don't handle manually, via JLink itself
(.getExpr
- (doto (MathLinkFactory/createLoopbackLink)
- (.put obj)
- (.endPacket))))
+ (doto (MathLinkFactory/createLoopbackLink)
+ (.put obj)
+ (.endPacket))))
(expr? [_this x]
(instance? Expr x))
(expr-element-type [_this container-type expr]
@@ -242,6 +243,6 @@
(defn create [kernel-link-atom opts]
(map->JLinkImpl
- {:opts opts
- :kernel-link-atom kernel-link-atom
- :packet-listener (->InfoPacketCaptureListener (atom nil))}))
+ {:opts opts
+ :kernel-link-atom kernel-link-atom
+ :packet-listener (->InfoPacketCaptureListener (atom nil))}))
diff --git a/src/wolframite/impl/protocols.clj b/src/wolframite/impl/protocols.clj
index e6bb94f..61b5034 100644
--- a/src/wolframite/impl/protocols.clj
+++ b/src/wolframite/impl/protocols.clj
@@ -1,5 +1,6 @@
(ns wolframite.impl.protocols
- (:import (java.awt Component)))
+ (:import
+ (java.awt Component)))
(defprotocol JLink
"A protocol to divorce the code from a direct dependency on JLink, so that it can be loaded
@@ -60,4 +61,4 @@
(^Component make-math-canvas! [this kernel-link]
(throw (IllegalStateException. "JLink not loaded!")))
(jlink-package-name [this]
- (throw (IllegalStateException. "JLink not loaded!"))))
+ (throw (IllegalStateException. "JLink not loaded!"))))
diff --git a/src/wolframite/impl/wolfram_syms/intern.clj b/src/wolframite/impl/wolfram_syms/intern.clj
index b7f2bf8..db77efd 100644
--- a/src/wolframite/impl/wolfram_syms/intern.clj
+++ b/src/wolframite/impl/wolfram_syms/intern.clj
@@ -1,8 +1,10 @@
(ns wolframite.impl.wolfram-syms.intern
"Interning of Wolfram symbols as Clojure vars, for convenience."
- (:require [clojure.walk :as walk]
- [clojure.walk])
- (:import (clojure.lang IMeta)))
+ (:require
+ [clojure.walk :as walk]
+ [clojure.walk])
+ (:import
+ (clojure.lang IMeta)))
(defn interned-var-val->symbol
"Turns the value of an [[clj-intern]]-ed Wolfram symbols into said symbol, if possible - otherwise, returns nil.
@@ -87,4 +89,4 @@
(if (qualified-symbol? form)
(symbol (name form))
form))
- form))
\ No newline at end of file
+ form))
diff --git a/src/wolframite/impl/wolfram_syms/wolfram_syms.clj b/src/wolframite/impl/wolfram_syms/wolfram_syms.clj
index c1efb62..d2c2595 100644
--- a/src/wolframite/impl/wolfram_syms/wolfram_syms.clj
+++ b/src/wolframite/impl/wolfram_syms/wolfram_syms.clj
@@ -1,6 +1,7 @@
(ns wolframite.impl.wolfram-syms.wolfram-syms
"Support for loading available symbols (fns & more) from Wolfram"
- (:require [wolframite.impl.wolfram-syms.intern :as intern]))
+ (:require
+ [wolframite.impl.wolfram-syms.intern :as intern]))
(defn fetch-all-wolfram-symbols [wl-eval]
(doall (->> (wl-eval '(EntityValue (WolframLanguageData) ["Name", "PlaintextUsage"] "EntityPropertyAssociation"))
@@ -32,7 +33,7 @@
(doall (->> (fetch-all-wolfram-symbols wl-eval)
(map (fn [{:keys [sym doc]}]
(intern/clj-intern
- sym
- {:intern/ns-sym ns-sym
- :intern/extra-meta {:doc (when (string? doc) ; could be `(Missing "NotAvailable")`
- doc)}}))))))
+ sym
+ {:intern/ns-sym ns-sym
+ :intern/extra-meta {:doc (when (string? doc) ; could be `(Missing "NotAvailable")`
+ doc)}}))))))
diff --git a/src/wolframite/impl/wolfram_syms/write_ns.clj b/src/wolframite/impl/wolfram_syms/write_ns.clj
index 582e5e2..48021bb 100644
--- a/src/wolframite/impl/wolfram_syms/write_ns.clj
+++ b/src/wolframite/impl/wolfram_syms/write_ns.clj
@@ -3,14 +3,15 @@
autocompletion (even in editors using static code analysis) and linters (clj-kondo only does
static code)"
(:require
- [clojure.string :as str]
- [clojure.java.io :as io]
[clojure.edn :as edn]
+ [clojure.java.io :as io]
+ [clojure.string :as str]
[wolframite.core :as core]
[wolframite.impl.wolfram-syms.intern :as intern]
[wolframite.impl.wolfram-syms.wolfram-syms :as wolfram-syms]
[wolframite.runtime.defaults :as defaults])
- (:import (java.io FileNotFoundException PushbackReader)))
+ (:import
+ (java.io FileNotFoundException PushbackReader)))
(comment
(-> (io/resource "wolframite/impl/wolfram_syms/write_ns/includes.clj")
@@ -97,24 +98,24 @@
(spit path
(str/join "\n"
(concat
- (map pr-str wolfram-ns-heading)
+ (map pr-str wolfram-ns-heading)
;; Add version info, similar to clojure's *clojure-version*; marked dynamic so
;; that clj doesn't complain about those *..*
- [(format "(def ^:dynamic *wolfram-version* %s)" wolfram-version)]
- [(format "(def ^:dynamic *wolfram-kernel-name* \"%s\")" wolfram-kernel-name)]
- (map pr-str (make-defs all-syms))
- (map pr-str (make-wolfram-ns-footer all-syms))
- [(inclusions-body-str!)] ; the w/fn macro etc.
- (some-> aliases (aliases->defs all-syms) (->> (map pr-str))))))
+ [(format "(def ^:dynamic *wolfram-version* %s)" wolfram-version)]
+ [(format "(def ^:dynamic *wolfram-kernel-name* \"%s\")" wolfram-kernel-name)]
+ (map pr-str (make-defs all-syms))
+ (map pr-str (make-wolfram-ns-footer all-syms))
+ [(inclusions-body-str!)] ; the w/fn macro etc.
+ (some-> aliases (aliases->defs all-syms) (->> (map pr-str))))))
(catch FileNotFoundException e
(throw (ex-info (format "Could not write to %s - does the parent dir exist?"
path)
{:path path, :cause (ex-message e)})))))))
-;(defmacro make-wolf-defs []
+; (defmacro make-wolf-defs []
; `(do ~@(make-defs)))
; USAGE: Use
-;(macroexpand '(make-wolf-defs))
+; (macroexpand '(make-wolf-defs))
(comment
@@ -125,5 +126,5 @@
(load-file "src/wolframite/wolfram.clj"))
(write-ns!
- "src/wolframite/wolfram.clj"
- {:aliases '{I Integrate}}))
+ "src/wolframite/wolfram.clj"
+ {:aliases '{I Integrate}}))
diff --git a/src/wolframite/impl/wolfram_syms/write_ns/includes.clj b/src/wolframite/impl/wolfram_syms/write_ns/includes.clj
index fcc1f87..c4e481f 100644
--- a/src/wolframite/impl/wolfram_syms/write_ns/includes.clj
+++ b/src/wolframite/impl/wolfram_syms/write_ns/includes.clj
@@ -1,18 +1,18 @@
(ns wolframite.impl.wolfram-syms.write-ns.includes
"The content is to be included in the generated `wolframite.wolfram` ns."
+ (:refer-clojure :only [defmacro let list])
(:require
- clojure.walk
- wolframite.impl.wolfram-syms.intern)
- (:refer-clojure :only [defmacro let list]))
+ [clojure.walk]
+ [wolframite.impl.wolfram-syms.intern]))
;; Cursive: resolve as defn; Kondo: TBD
;; TODO: Do we want to enable specs?!
-;(s/fdef fn
+; (s/fdef fn
; :args (s/cat :params :clojure.core.specs.alpha/params+body
; :body any?)
; :ret any?)
-;;--INCLUDE-START--
+;; --INCLUDE-START--
(defmacro fn
"Creates a Wolfram anonymous function with the given arguments and single expression body.
Example usage: `(wl/eval (w/Map (w/fn [x] (w/Plus x 1)) [1 2 3]))`"
diff --git a/src/wolframite/lib/helpers.clj b/src/wolframite/lib/helpers.clj
index 138bfe6..5e129f1 100644
--- a/src/wolframite/lib/helpers.clj
+++ b/src/wolframite/lib/helpers.clj
@@ -1,6 +1,7 @@
(ns wolframite.lib.helpers
- (:require [clojure.java.browse :refer [browse-url]]
- [wolframite.impl.wolfram-syms.intern :as intern]))
+ (:require
+ [clojure.java.browse :refer [browse-url]]
+ [wolframite.impl.wolfram-syms.intern :as intern]))
(defn help-link [fn-sym]
(format "https://reference.wolfram.com/language/ref/%s.html" fn-sym))
diff --git a/src/wolframite/lib/options.clj b/src/wolframite/lib/options.clj
index 5bd815d..b57fef3 100644
--- a/src/wolframite/lib/options.clj
+++ b/src/wolframite/lib/options.clj
@@ -1,46 +1,47 @@
-(ns wolframite.lib.options
- (:require [wolframite.runtime.defaults :as defaults]))
-
-(defn filter-params [current-options]
- (into {} (filter #(keyword? (key %)) current-options)))
-
-(defn filter-flags [current-options]
- (into {} (filter #(set? (first %)) current-options)))
-
-(defn filter-flag-sets
- [flag current-options]
- (filter #(some #{flag} %) (keys (filter-flags current-options))))
-
-(defn flags-into
- "Conjoins each flag in flags into hash-map *flags*, setting each such flag as the value
- of any keys that contain flag as an element."
- [current-options flags]
- (into current-options
- (for [flag flags
- active-set (filter-flag-sets flag current-options)]
- [active-set flag])))
-
-(defn params-into
- "Conjoins each key-value pair in options into hash-map *options*, conjoining each such pair
- only if options-keys contains that key."
- [current-options params]
- (into current-options
- (filter #(some #{(first %)} (keys (filter-params current-options))) params)))
-
-(defn options-into [current-options params flags]
- (flags-into (params-into current-options params) flags))
-
-(defn flag? [current-options flag]
- (not (nil? (some #{flag} (vals (filter-flags current-options))))))
-
-(defn flag?' [user-flags flag]
- (flag? (flags-into defaults/default-options user-flags) flag))
-
-;;
-
-(defn set-flag [flags f]
- (flags-into flags [f]))
-
-(defn aliases [base-list]
- (or (defaults/default-options base-list)
- (defaults/default-options :clojure-aliases)))
+(ns wolframite.lib.options
+ (:require
+ [wolframite.runtime.defaults :as defaults]))
+
+(defn filter-params [current-options]
+ (into {} (filter #(keyword? (key %)) current-options)))
+
+(defn filter-flags [current-options]
+ (into {} (filter #(set? (first %)) current-options)))
+
+(defn filter-flag-sets
+ [flag current-options]
+ (filter #(some #{flag} %) (keys (filter-flags current-options))))
+
+(defn flags-into
+ "Conjoins each flag in flags into hash-map *flags*, setting each such flag as the value
+ of any keys that contain flag as an element."
+ [current-options flags]
+ (into current-options
+ (for [flag flags
+ active-set (filter-flag-sets flag current-options)]
+ [active-set flag])))
+
+(defn params-into
+ "Conjoins each key-value pair in options into hash-map *options*, conjoining each such pair
+ only if options-keys contains that key."
+ [current-options params]
+ (into current-options
+ (filter #(some #{(first %)} (keys (filter-params current-options))) params)))
+
+(defn options-into [current-options params flags]
+ (flags-into (params-into current-options params) flags))
+
+(defn flag? [current-options flag]
+ (not (nil? (some #{flag} (vals (filter-flags current-options))))))
+
+(defn flag?' [user-flags flag]
+ (flag? (flags-into defaults/default-options user-flags) flag))
+
+;;
+
+(defn set-flag [flags f]
+ (flags-into flags [f]))
+
+(defn aliases [base-list]
+ (or (defaults/default-options base-list)
+ (defaults/default-options :clojure-aliases)))
diff --git a/src/wolframite/runtime/defaults.clj b/src/wolframite/runtime/defaults.clj
index d4f5fa0..76f96d5 100644
--- a/src/wolframite/runtime/defaults.clj
+++ b/src/wolframite/runtime/defaults.clj
@@ -1,7 +1,8 @@
(ns wolframite.runtime.defaults
"Flags and aliases for the Wolfram runtime."
- (:require clojure.set
- [clojure.walk :as walk]))
+ (:require
+ [clojure.set]
+ [clojure.walk :as walk]))
"TODO:
- Consider function that finds all non-numeric symbols (and not '- ') that start with a '-' and replace them with Minus[<symbol>]
@@ -13,14 +14,14 @@
#{:parse :no-parse} :parse
#{:evaluate :no-evaluate} :evaluate
#{:convert :no-convert} :convert
- ;#{:hash-maps :no-hash-maps} :hash-maps
- ;#{:functions :no-functions} :functions ;; ?? parse (Function ...) into our parse-fn instance?!
+ ; #{:hash-maps :no-hash-maps} :hash-maps
+ ; #{:functions :no-functions} :functions ;; ?? parse (Function ...) into our parse-fn instance?!
#{:aliases :no-aliases} :aliases
#{:N :no-N} :no-N ; :N -> use Expr.asArray on matrix' rows
- ;#{:verbose :no-verbose} :no-verbose
- ;#{:as-function
+ ; #{:verbose :no-verbose} :no-verbose
+ ; #{:as-function
; :as-expression} :as-expression
- ;#{:restore-defaults
+ ; #{:restore-defaults
; :no-restore-defaults} :no-restore-defaults
#{:full-form
:clojure-form} :clojure-form})
@@ -104,7 +105,7 @@
:parse true
:functions true
:aliases true
- ;:as-expression true
+ ; :as-expression true
:clojure-form true ;; FIXME: better name
:N false})
diff --git a/src/wolframite/runtime/system.clj b/src/wolframite/runtime/system.clj
index f60e1af..49cb7a1 100644
--- a/src/wolframite/runtime/system.clj
+++ b/src/wolframite/runtime/system.clj
@@ -135,8 +135,8 @@
(#{"osx" "macos" "Mac OS X" "mac"} os-str) :mac
(or (#{"win" "windows"} os-str) (str/starts-with? os-str "Windows")) :windows
:else (throw
- (ex-info (str "Did not recognise " os-str " as a supported OS.")
- {:os os-str})))))
+ (ex-info (str "Did not recognise " os-str " as a supported OS.")
+ {:os os-str})))))
(defn detect-os
"Tries to determine the current operating system.
@@ -191,7 +191,7 @@
The longest parental directory path that is common to both input paths.
"
[path1 path2]
- ;; TODO: This should be moved to some utility library.
+ ;; TODO: This should be moved to some utility library.
(let [sep "/"
rx-sep (re-pattern sep)]
(->> [path1 path2]
diff --git a/src/wolframite/specs.clj b/src/wolframite/specs.clj
index 012901f..a3370bf 100644
--- a/src/wolframite/specs.clj
+++ b/src/wolframite/specs.clj
@@ -1,8 +1,9 @@
(ns wolframite.specs
- (:require [wolframite.runtime.defaults :as defaults]
- [clojure.spec.alpha :as s]
- [clojure.spec.test.alpha :as st]
- clojure.set))
+ (:require
+ [clojure.set]
+ [clojure.spec.alpha :as s]
+ [clojure.spec.test.alpha :as st]
+ [wolframite.runtime.defaults :as defaults]))
(s/def :wl/flag defaults/all-flags)
(s/def :wl/flags (s/coll-of :wl/flag))
@@ -13,8 +14,8 @@
(s/def :wl/opts-map (s/keys :opt [:wl/flags :wl/aliases]))
(s/def :wl/args (s/alt
- :no-options (s/cat :body any?)
- :with-options (s/cat :opts-kw? :wl/opts-kw :opts-map (s/nilable :wl/opts-map) :body any?)))
+ :no-options (s/cat :body any?)
+ :with-options (s/cat :opts-kw? :wl/opts-kw :opts-map (s/nilable :wl/opts-map) :body any?)))
(comment ;; spec examples
@@ -33,12 +34,8 @@
(s/conform :wl/args [:opts {:flags [:parse/as-function :debug/verbose :convert/hash-maps]} '(Dot [1 3 4] [5 4 6])])
-
(let [args #_['(Dot [1 3 4] [5 4 6])] [:opts {:flags [:parse/as-function :debug/verbose :convert/hash-maps]} '(Dot [1 3 4] [5 4 6])]
[options-flag {:keys [opts-map body]}] (s/conform :wl/args args)]
(if (= :with-options options-flag)
[opts-map body]
- [body]))
-
-
- )
+ [body])))
diff --git a/src/wolframite/tools/clerk_helper.clj b/src/wolframite/tools/clerk_helper.clj
index efc9236..103f4e5 100644
--- a/src/wolframite/tools/clerk_helper.clj
+++ b/src/wolframite/tools/clerk_helper.clj
@@ -1,11 +1,12 @@
(ns wolframite.tools.clerk-helper
- (:require [wolframite.core :as wl]
- [nextjournal.clerk :as clerk]
- [nextjournal.clerk.webserver :as webserver]
- [nextjournal.beholder :as beholder]
- ;; [clj-http.client :as client]
- [clojure.java.io :as io]
- [wolframite.tools.hiccup :as h]))
+ (:require
+ ;; [clj-http.client :as client]
+ [clojure.java.io :as io]
+ [nextjournal.beholder :as beholder]
+ [nextjournal.clerk :as clerk]
+ [nextjournal.clerk.webserver :as webserver]
+ [wolframite.core :as wl]
+ [wolframite.tools.hiccup :as h]))
(defn view [form & {:keys [folded?]}]
(clerk/html (h/view* form folded?)))
diff --git a/src/wolframite/tools/experimental.clj b/src/wolframite/tools/experimental.clj
index 2e3eb71..ef887fa 100644
--- a/src/wolframite/tools/experimental.clj
+++ b/src/wolframite/tools/experimental.clj
@@ -1,11 +1,13 @@
(ns wolframite.tools.experimental
"Don't use. Subject to change without prior notice."
- (:require [wolframite.core :as wl]
- [wolframite.impl.jlink-instance :as jlink-instance]
- [wolframite.impl.protocols :as proto])
- (:import [javax.swing JFrame JPanel SwingUtilities]
- [java.awt Dimension]
- [com.wolfram.jlink MathGraphicsJPanel]))
+ (:require
+ [wolframite.core :as wl]
+ [wolframite.impl.jlink-instance :as jlink-instance]
+ [wolframite.impl.protocols :as proto])
+ (:import
+ (com.wolfram.jlink MathGraphicsJPanel)
+ (java.awt Dimension)
+ (javax.swing JFrame JPanel SwingUtilities)))
(defonce ^:private app (promise))
diff --git a/src/wolframite/tools/graphics.clj b/src/wolframite/tools/graphics.clj
index 75df755..de55cf1 100644
--- a/src/wolframite/tools/graphics.clj
+++ b/src/wolframite/tools/graphics.clj
@@ -3,14 +3,16 @@
;; Wolfram has You use MathCanvas when you want an AWT component and MathGraphicsJPanel when you
;; want a Swing component - see https://reference.wolfram.com/language/JLink/tutorial/CallingJavaFromTheWolframLanguage.html#20608
;; Notice that KernelLink also has evaluateToImage() and evaluateToTypeset() methods
- (:require [wolframite.impl.jlink-instance :as jlink-instance]
- [wolframite.impl.protocols :as proto]
- [wolframite.core :as wl])
- (:import (java.awt Color Component Frame)
- (java.awt.image BufferedImage)
- (javax.imageio ImageIO)
- (java.io ByteArrayInputStream)
- (java.awt.event WindowAdapter ActionEvent)))
+ (:require
+ [wolframite.core :as wl]
+ [wolframite.impl.jlink-instance :as jlink-instance]
+ [wolframite.impl.protocols :as proto])
+ (:import
+ (java.awt Color Component Frame)
+ (java.awt.event ActionEvent WindowAdapter)
+ (java.awt.image BufferedImage)
+ (java.io ByteArrayInputStream)
+ (javax.imageio ImageIO)))
(defn scaled
[x factor]
@@ -79,4 +81,3 @@
(ImageIO/read (ByteArrayInputStream. (.evaluateToImage (proto/kernel-link (jlink-instance/get)) "GeoGraphics[]" (int width) (int height) 600 true))))))
;; doesn't make much difference (maybe a bit), seems like we can go lower dpi, but we already get maximum by default (?)
-
diff --git a/src/wolframite/tools/hiccup.clj b/src/wolframite/tools/hiccup.clj
index e38f2b3..94a8a92 100644
--- a/src/wolframite/tools/hiccup.clj
+++ b/src/wolframite/tools/hiccup.clj
@@ -1,9 +1,11 @@
(ns wolframite.tools.hiccup
- (:require [wolframite.core :as wl]
- [scicloj.kindly.v4.kind :as kind]
- [wolframite.impl.jlink-instance :as jlink-instance]
- [wolframite.impl.protocols :as proto])
- (:import (java.util Base64)))
+ (:require
+ [scicloj.kindly.v4.kind :as kind]
+ [wolframite.core :as wl]
+ [wolframite.impl.jlink-instance :as jlink-instance]
+ [wolframite.impl.protocols :as proto])
+ (:import
+ (java.util Base64)))
(defn bytes->b64encodedString
[^bytes bs]
@@ -11,23 +13,23 @@
(defn img [b64img]
(kind/hiccup
- [:img {:src (format "data:image/jpeg;base64,%s" b64img)
- :style {:margin-top "1rem"}}]))
+ [:img {:src (format "data:image/jpeg;base64,%s" b64img)
+ :style {:margin-top "1rem"}}]))
(defn view* [form folded?]
(let [wl-str (wl/->wl form {:output-fn str})
input-img (.evaluateToImage (proto/kernel-link (jlink-instance/get)) wl-str 0 0 0 true)
b64img (bytes->b64encodedString input-img)]
(kind/hiccup
- [:div
- [:details {:open (not folded?)}
- [:summary [:h5 {:style {:display "inline"
- :cursor "pointer"
- :padding "0.5rem 1rem 0 1rem"}}
- wl-str]]
- [:div.wl-results
- [:hr]
- (img b64img)]]])))
+ [:div
+ [:details {:open (not folded?)}
+ [:summary [:h5 {:style {:display "inline"
+ :cursor "pointer"
+ :padding "0.5rem 1rem 0 1rem"}}
+ wl-str]]
+ [:div.wl-results
+ [:hr]
+ (img b64img)]]])))
(defn view
"View a given Wolframite `form` as Hiccup, Kindly compatible.
diff --git a/src/wolframite/tools/portal.clj b/src/wolframite/tools/portal.clj
index 07d24a6..82d1c07 100644
--- a/src/wolframite/tools/portal.clj
+++ b/src/wolframite/tools/portal.clj
@@ -1,7 +1,8 @@
(ns wolframite.tools.portal
"Integration with https://djblue.github.io/portal/"
- (:require [portal.api :as p]
- [wolframite.tools.hiccup :as h]))
+ (:require
+ [portal.api :as p]
+ [wolframite.tools.hiccup :as h]))
(defn view [form & {:keys [folded?]}]
(p/submit (with-meta (h/view* form folded?)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment