aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/meta/target/jvm/method.lux
blob: 629aaae949c23a174d43d7e43156859ee1eeb49a (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
(.require
 [library
  [lux (.except Type static public private)
   [abstract
    [equivalence (.only Equivalence)]
    ["[0]" monad (.only do)]]
   [control
    ["[0]" try]]
   [data
    ["[0]" product]
    [binary
     ["[0]" \\format (.only Format) (.use "[1]#[0]" monoid)]]
    [collection
     ["[0]" sequence (.only Sequence)]
     ["[0]" list]]]]]
 ["[0]" //
  ["[1][0]" modifier (.only Modifier modifiers)]
  ["[1][0]" index (.only Index)]
  ["[1][0]" attribute (.only Attribute)
   ["[2][0]" code]]
  ["[1][0]" constant (.only UTF8)
   ["[2][0]" pool (.only Pool Resource)]]
  ["[1][0]" bytecode (.only Bytecode)
   ["[2][0]" environment (.only Environment)]
   ["[2][0]" instruction]]
  ["[1][0]" type (.only Type)
   [descriptor (.only Descriptor)]
   ["[2][0]" category]
   ["[2][0]" signature (.only Signature)]]])

(type .public Method
  (Rec Method
    (Record
     [#modifier (Modifier Method)
      #name (Index UTF8)
      #descriptor (Index (Descriptor //category.Method))
      #attributes (Sequence Attribute)])))

(modifiers
 Method
 ["0001" public]
 ["0002" private]
 ["0004" protected]
 ["0008" static]
 ["0010" final]
 ["0020" synchronized]
 ["0040" bridge]
 ["0080" var_args]
 ["0100" native]
 ["0400" abstract]
 ["0800" strict]
 ["1000" synthetic]
 )

(def .public (method modifier name with_signature? type attributes code)
  (-> (Modifier Method) UTF8 Bit (Type //category.Method) (List (Resource Attribute)) (Maybe (Bytecode Any))
      (Resource Method))
  (do [! //pool.monad]
    [@name (//pool.utf8 name)
     @descriptor (//pool.descriptor (//type.descriptor type))
     attributes (|> (if with_signature?
                      (list.partial (//attribute.signature (//type.signature type)) attributes)
                      attributes)
                    (monad.all !)
                    (at ! each sequence.of_list))
     attributes (when code
                  {.#Some code}
                  (do !
                    [environment (when (if (//modifier.has? static modifier)
                                         (//environment.static type)
                                         (//environment.virtual type))
                                   {try.#Success environment}
                                   (in environment)
                                   
                                   {try.#Failure error}
                                   (function (_ _)
                                     {try.#Failure error}))
                     [environment line_number_table exceptions instruction output] (//bytecode.resolve environment code)
                     .let [bytecode (|> instruction //instruction.result \\format.instance)]
                     code_attributes (is (Resource (Sequence Attribute))
                                         (if (sequence.empty? line_number_table)
                                           (in sequence.empty)
                                           (do !
                                             [@line_number_table (//attribute.line_number_table line_number_table)]
                                             (in (sequence.sequence @line_number_table)))))
                     @code (//attribute.code [//code.#limit (the //environment.#limit environment)
                                              //code.#code bytecode
                                              //code.#exception_table exceptions
                                              //code.#attributes code_attributes])]
                    (in (sequence.suffix @code attributes)))
                  
                  {.#None}
                  (in attributes))]
    (in [#modifier modifier
         #name @name
         #descriptor @descriptor
         #attributes attributes])))

(def .public equivalence
  (Equivalence Method)
  (all product.equivalence
       //modifier.equivalence
       //index.equivalence
       //index.equivalence
       (sequence.equivalence //attribute.equivalence)
       ))

(def .public (format field)
  (Format Method)
  (`` (all \\format#composite
           (,, (with_template [<format> <slot>]
                 [(<format> (the <slot> field))]

                 [//modifier.format #modifier]
                 [//index.format #name]
                 [//index.format #descriptor]
                 [(\\format.sequence_16 //attribute.format) #attributes]))
           )))