Skip to content

Commit

Permalink
[#429] Drop support for :realize-max / :preset :termination-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
borkdude committed Oct 17, 2020
1 parent ac0b4a1 commit 4197294
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 129 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

For a list of breaking changes, check [here](#breaking-changes)

### >= 0.1.0 (unreleased)

- Removed `:realize-max` and `:preset :termination-safe`. In the light of
[#348](https://github.com/borkdude/sci/issues/348) it would be misleading to
claim that sci can guarantee termination within reasonable time.

## v0.1.0 (2020-06-16)

Thank to [@jeroenvandijk](https://github.com/jeroenvandijk), [@jjttjj](https://github.com/jjttjj), [@justone](https://github.com/justone), [@sogaiu](https://github.com/sogaiu) and [@armincerf](https://github.com/armincerf) for
Expand Down Expand Up @@ -85,6 +91,12 @@ Details about releases prior to v0.1.0 can be found

## Breaking changes

### >= 0.1.0

- Removed `:realize-max` and `:preset :termination-safe`. In the light of
[#348](https://github.com/borkdude/sci/issues/348) it would be misleading to
claim that sci can guarantee termination within reasonable time.

### v0.0.12

- `:row` and `:col` metadata have been renamed to `:line` and `:column` to be
Expand Down
21 changes: 4 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ This library works with:
- Clojure compiled with GraalVM native
- ClojureScript, even when compiled with `:advanced`, and (as a consequence) JavaScript

It is used in:
## Projects using sci

Sci is used in:

- [Babashka](https://github.com/borkdude/babashka). A Clojure scripting tool that plays well with Bash.
- [Bootleg](https://github.com/retrogradeorbit/bootleg). An HTML templating CLI.
Expand All @@ -49,6 +51,7 @@ It is used in:
- [Logseq](https://logseq.com). A local-only outliner notebook which supports both Markdown and Org mode.
- [Malli](https://github.com/metosin/malli). Plain data Schemas for Clojure/Script.
- [PCP](https://github.com/alekcz/pcp). Clojure Processor (PHP replacement).
- [Prose](https://github.com/JeremS/prose). Alternate syntax for Clojure, similar to what Pollen brings to Racket.
- [Spire](https://github.com/epiccastle/spire). Pragmatic provisioning using Clojure.

## Status
Expand Down Expand Up @@ -114,22 +117,6 @@ user=> (sci/eval-string "(inc 1)" {:deny '[inc]})
ExceptionInfo inc is not allowed! [at line 1, column 2] clojure.core/ex-info (core.clj:4739)
```

Preventing forever lasting evaluation of infinite sequences can be achieved with
`:realize-max`:

``` clojure
user=> (sci/eval-string "(vec (range))" {:realize-max 10})
ExceptionInfo Maximum number of elements realized: 10 [at line 1, column 1] clojure.core/ex-info (core.clj:4739)
```

The preset `:termination-safe`, which is currently `{:deny '[loop recur
trampoline] :realize-max 100}`, is helpful for making expressions terminate:

``` clojure
user=> (sci/eval-string "(loop [] (recur))" {:preset :termination-safe})
ExceptionInfo loop is not allowed! [at line 1, column 2] clojure.core/ex-info (core.clj:4739)
```

Providing a macro as a binding can be done by providing a normal function that:
- has `:sci/macro` on the metadata set to `true`
- has two extra arguments at the start for `&form` and `&env`:
Expand Down
4 changes: 2 additions & 2 deletions src/sci/impl/interpreter.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
[sci.impl.fns :as fns]
[sci.impl.interop :as interop]
[sci.impl.macros :as macros]
[sci.impl.max-or-throw :refer [max-or-throw]]
[sci.impl.opts :as opts]
[sci.impl.parser :as p]
[sci.impl.records :as records]
Expand Down Expand Up @@ -639,7 +638,8 @@
ret)]
;; for debugging:
;; (prn expr (meta expr) '-> ret)
(if-let [n (.get ^java.util.Map ctx :realize-max)]
ret
#_(if-let [n (.get ^java.util.Map ctx :realize-max)]
(max-or-throw ret (assoc ctx
:expression expr)
n)
Expand Down
67 changes: 0 additions & 67 deletions src/sci/impl/max_or_throw.cljc

This file was deleted.

15 changes: 3 additions & 12 deletions src/sci/impl/opts.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@
:imports imports
:load-fn load-fn)))))

(def presets
{:termination-safe
{:deny '[loop recur trampoline resolve]
:realize-max 100}})

(defn process-permissions [& permissions]
(not-empty (into #{} (comp cat (map strip-core-ns)) permissions)))

Expand Down Expand Up @@ -93,8 +88,6 @@
"Initializes options"
[{:keys [:bindings :env
:allow :deny
:realize-max
:preset ;; used by malli
:aliases
:namespaces
:classes
Expand All @@ -104,16 +97,14 @@
:uberscript ;; used by babashka, not public!
:readers
:reify]}]
(let [preset (get presets preset)
env (or env (atom {}))
(let [env (or env (atom {}))
imports (merge default-imports imports)
bindings bindings
_ (init-env! env bindings aliases namespaces imports load-fn)
ctx (merge {:env env
:bindings {}
:allow (process-permissions (:allow preset) allow)
:deny (process-permissions (:deny preset) deny)
:realize-max (or realize-max (:realize-max preset))
:allow (process-permissions allow)
:deny (process-permissions deny)
:features features
:readers readers
::ctx true
Expand Down
31 changes: 0 additions & 31 deletions test/sci/core_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -319,16 +319,6 @@
(is (thrown-with-msg? #?(:clj Exception :cljs js/Error)
#"allowed"
(tu/eval* "(clojure.core/inc 1)" {:deny '[clojure.core/inc]})))
(is (thrown-with-msg? #?(:clj Exception :cljs js/Error)
#"allowed"
(tu/eval* "(clojure.core/loop [] (recur))" {:preset :termination-safe})))
(is (thrown-with-msg? #?(:clj Exception :cljs js/Error)
#"allowed"
(tu/eval* "(eval '(loop [] (recur)))" {:preset :termination-safe})))
(is (thrown-with-msg? #?(:clj Exception :cljs js/Error)
#"allowed"
(tu/eval* "(resolve 'trampoline)" {:preset :termination-safe})))

(testing "for/doseq/dotimes use loop in a safe manner, so `{:deny '[loop recur]}` should not forbid it, see #141"
(is '(1 2 3) (tu/eval* "(for [i [1 2 3] j [4 5 6]] [i j])" {:deny '[loop recur]}))
(is (nil? (tu/eval* "(doseq [i [1 2 3]] i)" {:deny '[loop recur]})))
Expand All @@ -351,24 +341,6 @@
(testing "users cannot hack around sci.impl/needs-ctx"
(is (= [1 2] (eval* "(def f (with-meta (fn [ctx x] [ctx x]) {:sci.impl/needs-ctx true})) (f 1 2)")))))

(deftest realize-max-test
(when-not tu/native?
(let [d (try (tu/eval* "(reduce (fn [_ _]) (range 1000))" {:realize-max 100})
(catch #?(:clj clojure.lang.ExceptionInfo :cljs ExceptionInfo) e
(ex-data e)))]
(is (= :sci.error/realized-beyond-max (:type d)))))
(is (thrown-with-msg? #?(:clj clojure.lang.ExceptionInfo :cljs ExceptionInfo)
#"realized"
(tu/eval* "(reduce (fn [_ _]) (range 1000))" {:realize-max 100})))
(is (thrown-with-msg? #?(:clj clojure.lang.ExceptionInfo :cljs ExceptionInfo)
#"realized"
(doall (tu/eval* "(repeat 1)" {:realize-max 100}))))
(is (thrown-with-msg? #?(:clj clojure.lang.ExceptionInfo :cljs ExceptionInfo)
#"realized"
(doall (tu/eval* "(repeat 1)" {:preset :termination-safe}))))
(is (= (range 10) (tu/eval* "(range 10)" {:realize-max 100})))
(is (= (map #(* % %) (range 99)) (tu/eval* "(map #(* % %) (range 99))" {:realize-max 100}))))

(deftest idempotent-eval-test
(is (= '(foo/f1 foo/f2)
(eval* "(map #(let [[ns v] %] (symbol (str ns) (str v))) '[[foo f1] [foo f2]])")))
Expand All @@ -382,9 +354,6 @@
(is (thrown-with-data?
{:line 1 :column 11}
(with-out-str (eval* nil "(+ 1 2 3) (conj 1 0)"))))
(is (thrown-with-data?
{:line 1 :column 18}
(tu/eval* "(+ 1 2 3 4) (vec (range))" {:realize-max 100})))
(is (thrown-with-data?
{:line 1 :column 19}
(eval* "(+ 1 2 3 4 5) (do x)")))
Expand Down

0 comments on commit 4197294

Please sign in to comment.