aboutsummaryrefslogtreecommitdiff
path: root/src/lux/compiler/type.clj
blob: 7e2bc69617ac1eba0f5e76e0ecef1377dd19ff2e (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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
;;   Copyright (c) Eduardo Julian. 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 epl-v10.html at 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 lux.compiler.type
  (:require clojure.core.match
            clojure.core.match.array
            (lux [base :as & :refer [|do return* return fail fail* |let |case]]
                 [type :as &type])
            [lux.analyser.base :as &a]))

;; [Utils]
(defn ^:private variant$ [tag body]
  "(-> Text Analysis Analysis)"
  (&/T (&/V &a/$variant (&/T tag body))
       &type/$Void))

(defn ^:private tuple$ [members]
  "(-> (List Analysis) Analysis)"
  (&/T (&/V &a/$tuple members)
       &type/$Void))

(defn ^:private text$ [text]
  "(-> Text Analysis)"
  (&/T (&/V &a/$text text)
       &type/$Void))

(def ^:private $Nil
  "Analysis"
  (variant$ &/$Nil (tuple$ (&/|list))))

(defn ^:private Cons$ [head tail]
  "(-> Analysis Analysis Analysis)"
  (variant$ &/$Cons (tuple$ (&/|list head tail))))

;; [Exports]
(defn ->analysis [type]
  "(-> Type Analysis)"
  (|case type
    (&/$DataT ?class)
    (variant$ &/$DataT (text$ ?class))
    
    (&/$TupleT ?members)
    (variant$ &/$TupleT
              (&/fold (fn [tail head]
                        (Cons$ (->analysis head) tail))
                      $Nil
                      (&/|reverse ?members)))

    (&/$VariantT ?members)
    (variant$ &/$VariantT
              (&/fold (fn [tail head]
                        (Cons$ (->analysis head) tail))
                      $Nil
                      (&/|reverse ?members)))

    (&/$LambdaT ?input ?output)
    (variant$ &/$LambdaT (tuple$ (&/|list (->analysis ?input) (->analysis ?output))))

    (&/$AllT ?env ?name ?arg ?body)
    (variant$ &/$AllT
              (tuple$ (&/|list (|case ?env
                                 (&/$None)
                                 (variant$ &/$None (tuple$ (&/|list)))

                                 (&/$Some ??env)
                                 (variant$ &/$Some
                                           (&/fold (fn [tail head]
                                                     (|let [[hlabel htype] head]
                                                       (Cons$ (tuple$ (&/|list (text$ hlabel) (->analysis htype)))
                                                              tail)))
                                                   $Nil
                                                   (&/|reverse ??env))))
                               (text$ ?name)
                               (text$ ?arg)
                               (->analysis ?body))))

    (&/$BoundT ?name)
    (variant$ &/$BoundT (text$ ?name))

    (&/$AppT ?fun ?arg)
    (variant$ &/$AppT (tuple$ (&/|list (->analysis ?fun) (->analysis ?arg))))

    (&/$NamedT [?module ?name] ?type)
    (variant$ &/$NamedT (tuple$ (&/|list (tuple$ (&/|list (text$ ?module) (text$ ?name)))
                                         (->analysis ?type))))
    ))