SCI - Small Clojure Interpreter
22 August, 2024
The sci is the foundation library for clojure(script) application which allow evaluating from user input or used to provide "Clojure" DSL within the application.
The following are notes we collected while using and exploring how it works.
We can find out which namespaces is available by default inside sci like this:
(cljs.pprint/pprint
(-> (sci.impl.opts/init {}) ;; <--- Initialize the context
:env ;; <--- This is the environment
deref
:namespaces
keys
(->> (sort-by str) (into []))))
[clojure.core
clojure.edn
clojure.repl
clojure.set
clojure.string
clojure.template
clojure.walk
sci.impl.deftype
sci.impl.protocols
sci.impl.records
user]
The environment contains below keys:
[:async-load-fn
:class->opts
:imports
:js-libs
:load-fn
:namespaces
:ns-aliases
:public-class
:raw-classes]
To allow other clojure(script) libraries to be used from sci eval-string
, we
must provide the var mappings values for :namespaces
option, as shown in the
example below.
(sci.core/eval-string
"(e/->infix (e/square (e/sin (e/+ 'a 3))))"
{:namespaces {'emmy.env {'+ emmy.env/+
'->infix emmy.env/->infix
'square emmy.env/square
'sin emmy.env/sin}}
:ns-aliases {'e 'emmy.env}})
;; =>
"sinĀ²(a + 3)"
Some popular library which is known to be used inside sci, e.g. emmy, already provide some means of config to ease the process. Above example can be simplified like below.
(sci.core/eval-string
"(e/->infix (e/square (e/sin (e/+ 'a 3))))"
(merge
emmy.sci/config
{:ns-aliases '{e emmy.env}}))
"sinĀ²(a + 3)"