-
Notifications
You must be signed in to change notification settings - Fork 215
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #792 from frenchy64/frenchy64-recursive-non-termin…
…ation Fix recursive `:+` generators
- Loading branch information
Showing
5 changed files
with
221 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
(ns malli.generator-ast | ||
"For inspecting a malli's generator as data. See `generator-ast`" | ||
(:require [clojure.java.io :as io] | ||
[clojure.string :as str] | ||
[clojure.walk :as walk] | ||
[malli.generator :as mg])) | ||
|
||
(let [s (-> (slurp (io/resource "malli/generator.cljc")) | ||
;; change the namespace | ||
(str/replace-first "(ns malli.generator" "(ns malli.generator-ast") | ||
;; change the `gen` alias to the AST version | ||
(str/replace-first "clojure.test.check.generators" "malli.generator-debug"))] | ||
;; eval ns form first so keywords can be resolved in the right namespace | ||
(eval (read-string {:read-cond :allow :features #{:clj}} s)) | ||
(eval (read-string {:read-cond :allow :features #{:clj}} (str "(do " s ")")))) | ||
|
||
(defn generator-ast | ||
"Return a malli schema's generator as an AST." | ||
([?schema] | ||
(generator-ast ?schema nil)) | ||
([?schema options] | ||
(walk/postwalk | ||
(fn [g] | ||
(if (mg/-unreachable-gen? g) | ||
{:op :unreachable} | ||
g)) | ||
(generator ?schema (assoc options ::mg/generator-ast true))))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
(ns malli.generator-ast-test | ||
(:require [clojure.pprint :refer [pprint]] | ||
[clojure.test :refer [are deftest is testing]] | ||
[malli.generator-ast :as ast])) | ||
|
||
(deftest generator-ast-test | ||
(is (= '{:op :recursive-gen, | ||
:rec-gen | ||
{:op :one-of, | ||
:generators | ||
[{:op :boolean} | ||
{:op :tuple, | ||
:generators [{:op :elements, :coll [:not]} {:op :boolean}]} | ||
{:op :tuple, | ||
:generators | ||
[{:op :elements, :coll [:and]} | ||
{:op :vector, :generator {:op :recur}}]} | ||
{:op :tuple, | ||
:generators | ||
[{:op :elements, :coll [:or]} | ||
{:op :vector, :generator {:op :recur}}]}]}, | ||
:scalar-gen | ||
{:op :one-of, | ||
:generators | ||
[{:op :boolean} | ||
{:op :tuple, | ||
:generators [{:op :elements, :coll [:not]} {:op :boolean}]} | ||
{:op :tuple, | ||
:generators | ||
[{:op :elements, :coll [:and]} {:op :return, :value ()}]} | ||
{:op :tuple, | ||
:generators | ||
[{:op :elements, :coll [:or]} {:op :return, :value ()}]}]}} | ||
(ast/generator-ast | ||
[:schema | ||
{:registry | ||
{::formula | ||
[:or | ||
:boolean | ||
[:tuple [:enum :not] :boolean] | ||
[:tuple [:enum :and] [:* [:ref ::formula]]] | ||
[:tuple [:enum :or] [:* [:ref ::formula]]]]}} | ||
[:ref ::formula]]))) | ||
(is (= '{:op :recursive-gen, | ||
:rec-gen | ||
{:op :one-of, | ||
:generators | ||
[{:op :boolean} | ||
{:op :tuple, | ||
:generators [{:op :elements, :coll [:not]} {:op :boolean}]} | ||
{:op :tuple, | ||
:generators | ||
[{:op :elements, :coll [:and]} | ||
{:op :not-empty, :gen {:op :vector, :generator {:op :recur}}}]} | ||
{:op :tuple, | ||
:generators | ||
[{:op :elements, :coll [:or]} | ||
{:op :not-empty, :gen {:op :vector, :generator {:op :recur}}}]}]}, | ||
:scalar-gen | ||
{:op :one-of, | ||
:generators | ||
[{:op :boolean} | ||
{:op :tuple, | ||
:generators [{:op :elements, :coll [:not]} {:op :boolean}]}]}} | ||
(ast/generator-ast | ||
[:schema | ||
{:registry | ||
{::formula | ||
[:or | ||
:boolean | ||
[:tuple [:enum :not] :boolean] | ||
[:tuple [:enum :and] [:+ [:ref ::formula]]] | ||
[:tuple [:enum :or] [:+ [:ref ::formula]]]]}} | ||
[:ref ::formula]])))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
(ns malli.generator-debug | ||
"Drop-in replacement for clojure.test.check.generators that returns AST's | ||
instead of generators." | ||
(:refer-clojure :exclude [vector char keyword boolean not-empty symbol])) | ||
|
||
(defmacro such-that [& args] (let [args (vec args)] `{:op :such-that :args-form '~args :args ~args})) | ||
(def any {:op :any}) | ||
(def any-printable {:op :any-printable}) | ||
(defn double* [& args] {:op :double* :args args}) | ||
(defmacro fmap [& args] (let [args (vec args)] `{:op :fmap :args-form '~args :args ~args})) | ||
(defmacro vector | ||
([generator] {:op :vector :generator generator}) | ||
([generator num-elements] {:op :vector :generator generator :num-elements num-elements}) | ||
([generator min-elements max-elements] | ||
{:op :vector :generator generator :min-elements min-elements :max-elements max-elements})) | ||
(defmacro vector-distinct [& args] (let [args (vec args)] `{:op :vector-distinct :args-form '~args :args ~args})) | ||
(def char {:op :char}) | ||
(def nat {:op :nat}) | ||
(def char-alphanumeric {:op :char-alphanumeric}) | ||
(def string-alphanumeric {:op :string-alphanumeric}) | ||
(defn sized [& args] {:op :sized :args args}) | ||
(defn return [value] {:op :return :value value}) | ||
(defn one-of [generators] {:op :one-of :generators generators}) | ||
(defn tuple [& generators] {:op :tuple :generators (vec generators)}) | ||
(defn recursive-gen [rec scalar] | ||
{:op :recursive-gen | ||
:rec-gen (rec {:op :recur}) | ||
:scalar-gen scalar}) | ||
(def keyword {:op :keyword}) | ||
(def keyword-ns {:op :keyword-ns}) | ||
(def symbol {:op :symbol}) | ||
(def symbol-ns {:op :symbol-ns}) | ||
(def s-pos-int {:op :s-pos-int}) | ||
(def s-neg-int {:op :s-neg-int}) | ||
(defn elements [coll] {:op :elements :coll coll}) | ||
(defn large-integer* [& args] {:op :large-integer* :args args}) | ||
(def boolean {:op :boolean}) | ||
(def uuid {:op :uuid}) | ||
(defn not-empty [gen] {:op :not-empty :gen gen}) | ||
(defn generator? [& args] (assert nil "no stub for generator?")) | ||
(defn call-gen [& args] (assert nil "no stub for call-gen")) | ||
(defn make-size-range-seq [& args] (assert nil "no stub for make-size-range-seq")) | ||
(defn lazy-random-states [& args] (assert nil "no stub for lazy-random-states")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters