aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/control/function/named.lux
blob: 91eeb4c6c1d89b141026c59f956f285c81d877cf (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
... https://en.wikipedia.org/wiki/Named_parameter
(.require
 [library
  [lux (.except def)
   [abstract
    ["[0]" monad (.only do)]]
   [control
    ["?" parser]
    ["[0]" maybe]
    ["[0]" exception (.only Exception)]]
   [data
    ["[0]" text (.only)
     ["%" \\format]]
    [collection
     ["[0]" list (.use "[1]#[0]" monad)]
     ["[0]" set]
     ["[0]" dictionary]]]
   [math
    [number
     ["n" nat]]]
   ["[0]" meta (.only)
    ["[0]" code (.only)
     ["?[1]" \\parser]]
    [macro (.only with_symbols)
     [syntax (.only syntax)
      ["[0]" export]]]]]])

(exception.def .public (duplicate_parameters [definition parameters])
  (Exception [Symbol (List Text)])
  (exception.report
   (list ["Definition" (%.symbol definition)]
         ["Parameters" (%.list %.text parameters)])))

(exception.def .public (invalid_parameters [definition expected actual])
  (Exception [Symbol (List Text) (List Text)])
  (exception.report
   (list ["Definition" (%.symbol definition)]
         ["Expected" (%.list %.text expected)]
         ["Actual" (%.list %.text actual)])))

(.def .public def
  (syntax (_ [[exported? [name parameters] type body]
              (export.with (all ?.and
                                (?code.form (?.and ?code.local (?.some ?code.local)))
                                ?code.any
                                ?code.any))])
    (do meta.monad
      [here meta.current_module_name]
      (if (n.= (list.size parameters)
               (set.size (set.of_list text.hash parameters)))
        (with_symbols [g!function g!parameters g!_ g!it]
          (with_expansions [<invalid_parameters> (meta.failure (exception.error ..invalid_parameters [(symbol (, (code.symbol [here name])))
                                                                                                      (list (,* (list#each code.text parameters)))
                                                                                                      (dictionary.keys (, g!parameters))]))]
            (in (list (` (.def (, exported?) ((, g!function) (,* (list#each code.local parameters)))
                           (, type)
                           (, body)))
                      (` (.def (, exported?) (, (code.local name))
                           (syntax ((, (code.local name)) [(, g!parameters) (?.some (?.and ?code.local ?code.any))])
                             (let [(, g!parameters) (dictionary.of_list text.hash (, g!parameters))]
                               (when (dictionary.size (, g!parameters))
                                 (, (code.nat (list.size parameters)))
                                 (when (monad.each maybe.monad
                                                   (function ((, g!_) (, g!it))
                                                     (dictionary.value (, g!it) (, g!parameters)))
                                                   (list (,* (list#each code.text parameters))))
                                   {.#Some (, g!parameters)}
                                   (of meta.monad (,' in)
                                       (list (` ((, g!function) ((,' .,*) (, g!parameters))))))
                                   
                                   {.#None}
                                   <invalid_parameters>)

                                 (, g!_)
                                 <invalid_parameters>)))))))))
        (meta.failure (exception.error ..duplicate_parameters [[here name] parameters]))))))