aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/meta/compiler/language/lux/phase/translation/python/function.lux
blob: a17372cfe01e56af4d84d001a8a3acb2fb1dfbb9 (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
... 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
      ["_" python (.only SVar 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]" synthesis]
    ["[0]" phase]
    ["[1][0]" translation]
    ["//[1]" ///
     [arity (.only Arity)]
     [reference
      [variable (.only Register Variable)]]
     [meta
      [archive (.only Archive)
       ["[0]" artifact]]
      ["[0]" cache
       [dependency
        ["[1]" 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 argsO+ functionO))))

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

(def (with_closure function_id @function inits function_definition)
  (-> artifact.ID SVar (List (Expression Any)) (Statement Any) (Operation (Expression Any)))
  (when inits
    {.#End}
    (do phase.monad
      [_ (/////translation.execute! function_definition)
       _ (/////translation.save! function_id {.#None} function_definition)]
      (in @function))

    _
    (do [! phase.monad]
      [.let [declaration (_.def @function
                           (|> (list.enumeration inits)
                               (list#each (|>> product.left ..capture)))
                           (all _.then
                                function_definition
                                (_.return @function)))]
       _ (/////translation.execute! declaration)
       _ (/////translation.save! function_id {.#None} declaration)]
      (in (_.apply inits @function)))))

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

(def .public (function statement expression archive [environment arity bodyS])
  (-> Phase! (Translator (Abstraction synthesis.Term)))
  (do [! phase.monad]
    [dependencies (cache.dependencies archive bodyS)
     [[function_module function_artifact] body!] (/////translation.with_new_context archive dependencies
                                                   (/////translation.with_anchor 1
                                                     (statement expression archive bodyS)))
     environment (monad.each ! (expression archive) environment)
     .let [@curried (_.var "curried")
           arityO (|> arity .int _.int)
           @num_args (_.var "num_args")
           @self (_.var (///reference.artifact [function_module function_artifact]))
           apply_poly (.function (_ args func)
                        (_.apply (list (_.splat_poly args)) func))
           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))]]
    (with_closure function_artifact @self environment
      (_.def @self (list (_.poly @curried))
        (all _.then
             (_.set (list @num_args) (_.len/1 @curried))
             (<| (_.if (|> @num_args (_.= arityO))
                   (<| (_.then initialize!)
                       //loop.set_scope
                       body!))
                 (_.if (|> @num_args (_.> arityO))
                   (let [arity_inputs (_.slice (_.int +0) arityO @curried)
                         extra_inputs (_.slice arityO @num_args @curried)]
                     (_.return (|> @self
                                   (apply_poly arity_inputs)
                                   (apply_poly extra_inputs)))))
                 ... (|> @num_args (_.< arityO))
                 (let [@next (_.var "next")
                       @missing (_.var "missing")]
                   (all _.then
                        (_.def @next (list (_.poly @missing))
                          (_.return (|> @self (apply_poly (|> @curried (_.+ @missing))))))
                        (_.return @next)
                        )))
             )))
    ))