aboutsummaryrefslogtreecommitdiff
path: root/src/lux/analyser/def.clj
blob: c8994bc67ea3f939f3c2382069f15fc100c3e300 (plain)
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
(ns lux.analyser.def
  (:require [clojure.core.match :refer [match]]
            (lux [base :as & :refer [exec return fail
                                     if-m try-all-m map-m mapcat-m reduce-m
                                     assert!]])
            [lux.analyser.base :as &&]))

;; [Exports]
(defn defined? [module name]
  (fn [state]
    [::&/ok [state (get-in state [::&/modules module name :defined?])]]))

(defn annotated? [module name]
  (fn [state]
    [::&/ok [state (boolean (get-in state [::&/modules module name]))]]))

(defn macro? [module name]
  (fn [state]
    [::&/ok [state (boolean (get-in state [::&/modules module :macros name]))]]))

(defn annotate [module name access type]
  (fn [state]
    (let [full-name (str module &/+name-separator+ name)
          bound [::&&/Expression [::&&/global module name] type]]
      [::&/ok [(-> state
                   (assoc-in [::&/modules module name] {:args-n [:None]
                                                        :access access
                                                        :type   type
                                                        :defined? false})
                   (update-in [::&/global-env] merge {full-name bound, name bound}))
               nil]])))

(defn declare-macro [module name]
  (fn [state]
    [::&/ok [(assoc-in state [::&/modules module :macros name] true)
             nil]]))

(defn define [module name]
  (if-m (annotated? module name)
        (fn [state]
          [::&/ok [(assoc-in state [::&/modules module name :defined?] true)
                   nil]])
        (fail (str "[Analyser Error] Can't define an unannotated element: " name))))