aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/ruby/function.lux
blob: 873c10419fd44e72ecf29806c059ef2c5dea0ca4 (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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
... This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
... If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.

(.require
 [library
  [lux (.except function)
   [abstract
    ["[0]" monad (.only do)]]
   [data
    ["[0]" product]
    [text
     ["%" \\format (.only format)]]
    [collection
     ["[0]" list (.use "[1]#[0]" functor mix)]]]
   [meta
    [compiler
     [target
      ["_" ruby (.only LVar GVar Expression Statement)]]]]]]
 ["[0]" //
  [runtime (.only Operation Phase Translator Phase! Translator!)]
  ["[1][0]" reference]
  ["[1][0]" when]
  ["[1][0]" loop]
  ["/[1]" //
   ["[1][0]" reference]
   ["//[1]" ///
    [analysis (.only Environment Abstraction Reification)]
    ["[0]" phase]
    ["[0]" synthesis]
    ["[1][0]" translation]
    ["//[1]" ///
     [arity (.only Arity)]
     [reference
      [variable (.only Register Variable)]]
     [meta
      ["[0]" cache
       [dependency
        ["[1]/[0]" artifact]]]]]]]])

(def .public (apply expression archive [functionS argsS+])
  (Translator (Reification synthesis.Term))
  (do [! phase.monad]
    [functionO (expression archive functionS)
     argsO+ (monad.each ! (expression archive) argsS+)]
    (in (_.apply_lambda argsO+ functionO))))

(def .public capture
  (-> Register LVar)
  (|>> (///reference.foreign //reference.system) as_expected))

(def (with_closure inits self function_definition)
  (-> (List Expression) Text Expression [Statement Expression])
  (let [@self (_.global self)]
    (when inits
      {.#End}
      [(_.set (list @self) function_definition)
       @self]

      _
      [(_.set (list @self) (_.lambda {.#None}
                                     [(|> (list.enumeration inits)
                                          (list#each (|>> product.left ..capture)))
                                      (let [@self (_.local self)]
                                        (all _.then
                                             (_.set (list @self) function_definition)
                                             (_.return @self)))]))
       (_.apply_lambda inits @self)])))

(def input
  (|>> ++ //when.register))

(def .public (function statement expression archive [environment arity bodyS])
  (-> Phase! (Translator (Abstraction synthesis.Term)))
  (do [! phase.monad]
    [dependencies (cache/artifact.dependencies archive bodyS)
     [[function_module function_artifact] body!] (/////translation.with_new_context archive dependencies
                                                   (/////translation.with_anchor 1
                                                     (statement expression archive bodyS)))
     closureO+ (monad.each ! (expression archive) environment)
     .let [function_name (///reference.artifact [function_module function_artifact])
           @curried (_.local "curried")
           arityO (|> arity .int _.int)
           limitO (|> arity -- .int _.int)
           @num_args (_.local "num_args")
           @self (is _.Location
                     (when closureO+
                       {.#End}
                       (_.global function_name)

                       _
                       (_.local function_name)))
           initialize_self! (_.set (list (//when.register 0)) @self)
           initialize! (list#mix (.function (_ post pre!)
                                   (all _.then
                                        pre!
                                        (_.set (list (..input post)) (_.item (|> post .int _.int) @curried))))
                                 initialize_self!
                                 (list.indices arity))
           [declaration instatiation] (with_closure closureO+ function_name
                                        (_.lambda {.#None}
                                                  [(list (_.variadic @curried))
                                                   (all _.then
                                                        (_.set (list @num_args) (_.the "length" @curried))
                                                        (<| (_.if (|> @num_args (_.= arityO))
                                                              (<| (_.then initialize!)
                                                                  //loop.with_scope
                                                                  body!))
                                                            (_.if (|> @num_args (_.> arityO))
                                                              (let [slice (.function (_ from to)
                                                                            (_.array_range from to @curried))
                                                                    arity_args (_.splat (slice (_.int +0) limitO))
                                                                    output_func_args (_.splat (slice arityO @num_args))]
                                                                (_.return (|> @self
                                                                              (_.apply_lambda (list arity_args))
                                                                              (_.apply_lambda (list output_func_args))))))
                                                            ... (|> @num_args (_.< arityO))
                                                            (let [@missing (_.local "missing")]
                                                              (_.return (_.lambda {.#None}
                                                                                  [(list (_.variadic @missing))
                                                                                   (_.return (|> @self
                                                                                                 (_.apply_lambda (list (_.splat (|> (_.array (list))
                                                                                                                                    (_.do "concat" (list @curried) {.#None})
                                                                                                                                    (_.do "concat" (list @missing) {.#None})))))))]))))
                                                        )]))]
     _ (/////translation.execute! declaration)
     _ (/////translation.save! function_artifact {.#None} declaration)]
    (in instatiation)))