/
trammel.clj
62 lines (54 loc) · 1.8 KB
/
trammel.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
;;; trammel.clj -- Contracts programming library for Clojure
;; by Michael Fogus - http://fogus.me/fun/
;; May 26, 2010
;; Copyright (c) Michael Fogus, 2010. All rights reserved. The use
;; and distribution terms for this software are covered by the Eclipse
;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
;; which can be found in the file COPYING the root of this
;; distribution. By using this software in any fashion, you are
;; agreeing to be bound by the terms of this license. You must not
;; remove this notice, or any other, from this software.
(ns fogus.me.trammel
(:use fogus.me.trammel.impl))
(defmacro contract
[& forms]
(let [name (if (symbol? (first forms))
(first forms)
nil)]
(list* 'fn name
(collect-bodies
(if name
(rest forms)
forms)))))
(defmacro with-contracts
([f] f)
([f contract] (list 'partial contract f))
([f contract & more]
`(with-contracts (with-contracts ~f ~contract) ~@more)))
(defmacro defconstrainedfn
[name & body]
(let [mdata (if (string? (first body))
{:doc (first body)}
{})
body (if (:doc mdata)
(next body)
body)
body (for [bd (build-forms-map body)]
(let [arg (first (keys bd))
b (first (vals bd))]
(list* arg
{:pre (vec (b '(:requires)))
:post (vec (b '(:ensures)))}
(b '(:body)))))]
`(defn ~name
~(:doc mdata)
~@body)))
(defmacro kontract [& forms]
(let [name (if (symbol? (first forms))
(first forms)
nil)]
(list* 'fn name
(kollect-bodies
(if name
(rest forms)
forms)))))