-
-
Notifications
You must be signed in to change notification settings - Fork 46
/
definitions.clj
60 lines (53 loc) · 2 KB
/
definitions.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
(ns polylith.clj.core.workspace-clj.definitions
(:require [clojure.string :as str]
[polylith.clj.core.util.interface :as util]))
(def ->generic-type {'def "data"
'defn "function"
'defmacro "macro"})
(defn definition? [code]
(if (list? code)
(let [f (first code)
private? (-> code second meta :private)]
(and (not private?)
(or (= f 'def)
(= f 'defn)
(= f 'defmacro))))
false))
(defn filter-statements [statements]
(filterv definition?
; Drops the namespace declaration on top of the file
(drop 1 statements)))
(defn sub-namespace [namespace interface-ns]
(when (not= namespace interface-ns)
(str/join "." (drop 1 (str/split namespace #"\.")))))
(defn parameter [name]
(let [type (-> name meta :tag)]
(if type
{:name (str name)
:type (str "^" type)}
{:name (str name)})))
(defn function [namespace type name code interface-ns]
(let [sub-ns (sub-namespace namespace interface-ns)
parameters (mapv parameter (first code))
str-name (str name)
str-type (str type)]
(util/ordered-map :name str-name
:type str-type
:parameters parameters
:sub-ns sub-ns)))
(defn definitions
"Takes a statement (def, defn or defmacro) from source code
and returns a vector of definitions."
[namespace statement interface-ns]
(let [type (-> statement first ->generic-type)
name (second statement)
code (drop-while #(not (or (list? %)
(vector? %)))
statement)]
(if (= "data" type)
[(util/ordered-map :name (str name)
:type (str type)
:sub-ns (sub-namespace namespace interface-ns))]
(if (-> code first vector?)
[(function namespace type name code interface-ns)]
(mapv #(function namespace type name % interface-ns) code)))))