Skip to content

Instantly share code, notes, and snippets.



Last active Oct 29, 2016
What would you like to do?
Useless Language AST (clojure.spec)
;; The AST consists of declarations and calls.
(s/def :lang/ast
(s/keys :req [:lang/declarations :lang/calls]))
;; Throughout, we'll use variables/calls identified by their name.
(s/def :lang/name
(s/and string? #(re-matches #"[a-z]+" %)))
(s/def :lang/variable-name
(s/def :lang/call-name
;; Declarations are maps containing a single variable name.
(s/def :lang/declarations
(s/coll-of :lang/declaration))
(s/def :lang/declaration
(s/keys :req [:lang/variable-name]))
;; Calls are maps containing the name of the call and the variables to
;; be used as parameters.
(s/def :lang/calls
(s/coll-of :lang/call))
(s/def :lang/call
(s/keys :req [:lang/call-name :lang/call-parameters]))
(s/def :lang/call-parameters
(s/coll-of :lang/variable-name))
(def ^:dynamic *variable-names* nil)
(defn variable-name-declared-before-use?
(or (not *variable-names*)
(contains? *variable-names* n)))
(s/def :lang/variable-name
(s/and :lang/name variable-name-declared-before-use?))
(defn verify-ast
[{:keys [lang/declarations] :as ast}]
(let [variable-names (set (map :lang/variable-name declarations))]
(binding [*variable-names* variable-names]
(s/explain-data :lang/ast ast))))
(defn variable-names-declared-before-use?
[{:keys [lang/declarations lang/calls]}]
(let [valid-variable-name? (set (map :lang/variable-name declarations))
used-variable-names (mapcat :lang/call-parameters calls)]
(every? valid-variable-name? used-variable-names)))
(s/def :lang/ast-with-predicates
(s/and :lang/ast
(s/def :lang/valid-ast
(fn [ast]
{:lang/variable-name (variable-name-declared? ast)
:lang/declarations variable-names-unique?})))
;; or as constant specialisation:
(defn valid-ast-spec
{:lang/variable-name (variable-name-declared? ast)
:lang/declarations variable-names-unique?}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.