aboutsummaryrefslogtreecommitdiff
path: root/src/lux/analyser/def.clj
blob: eb637f66b0dbe8070da7a441669324b07fb1bf2a (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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
(ns lux.analyser.def
  (:require (clojure [template :refer [do-template]])
            [clojure.core.match :as M :refer [matchv]]
            clojure.core.match.array
            (lux [base :as & :refer [|do return return* fail]])
            [lux.analyser.base :as &&]))

;; [Exports]
(def init-module
  (&/R "lux;defs" (&/|table)
       "lux;macros" (&/|table)))

(do-template [<name> <category>]
  (defn <name> [module name]
    (fn [state]
      (return* state
               (->> state (&/get$ "lux;modules") (&/|get module) (&/get$ <category>) (&/|contains? name)))))

  defined? "lux;defs"
  macro?   "lux;macros"
  )

(defn declare-macro [module name]
  (fn [state]
    (return* (&/update$ "lux;modules" (fn [ms] (&/|update module (fn [m] (&/update$ "lux;macros" #(&/|put name true %) m)) ms)) state)
             nil)))

(defn define [module name type]
  (fn [state]
    (let [full-name (str module &/+name-separator+ name)
          bound (&/V "Expression" (&/T (&/V "global" (&/T module name)) type))]
      (return* (->> state
                    (&/update$ "lux;modules" (fn [ms] (&/|update module (fn [m] (&/update$ "lux;defs" #(&/|put name type %) m)) ms)))
                    (&/update$ "lux;global-env" #(matchv ::M/objects [%]
                                                   [["lux;None" _]]
                                                   (assert false)

                                                   [["lux;Some" table]]
                                                   (&/V "lux;Some" (&/update$ "lux;locals" (fn [locals]
                                                                                             (&/update$ "lux;mappings" (fn [mappings]
                                                                                                                         (&/|merge (&/|table full-name bound, name bound)
                                                                                                                                   mappings))
                                                                                                        locals))
                                                                              table))
                                                   )))
               nil))))

(defn module-exists? [name]
  (fn [state]
    (return* state
             (->> state (&/get$ "lux;modules") (&/|contains? name)))))

(defn unalias-module [name]
  (fn [state]
    (if-let [real-name (->> state (&/get$ "lux;module-aliases") (&/|get name))]
      (return* state real-name)
      (fail "Unknown alias."))))