... 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/.

(.using
 [library
  [lux (.except Type
                static public private)
   [abstract
    [equivalence (.only Equivalence)]
    ["[0]" monad]]
   [data
    ["[0]" product]
    ["[0]" binary
     ["[1]F" \\injection (.only Injection) (.use "[1]#[0]" monoid)]]
    [collection
     ["[0]" sequence (.only Sequence)]]]
   [macro
    ["[0]" template]]]]
 ["[0]" //
  ["[0]" modifier (.only Modifier modifiers)]
  ["[1][0]" constant
   [utf8 (.only UTF8)]
   ["[1]/[0]" pool (.only Pool Resource)]]
  ["[1][0]" index (.only Index)]
  ["[1][0]" attribute (.only Attribute)]
  ["[1][0]" type (.only Type)
   [category (.only Value)]
   [descriptor (.only Descriptor)]]])

(every .public Field
  (Rec Field
    (Record
     [#modifier (Modifier Field)
      #name (Index UTF8)
      #descriptor (Index (Descriptor Value))
      #attributes (Sequence Attribute)])))

(modifiers
 Field
 ["0001" public]
 ["0002" private]
 ["0004" protected]
 ["0008" static]
 ["0010" final]
 ["0040" volatile]
 ["0080" transient]
 ["1000" synthetic]
 ["4000" enum]
 )

(the .public equivalence
  (Equivalence Field)
  (all product.equivalence
       modifier.equivalence
       //index.equivalence
       //index.equivalence
       (sequence.equivalence //attribute.equivalence)))

(alias [=]
       ..equivalence)

(the .public (as_binary field)
  (Injection Field)
  (`` (all binaryF#composite
           (,, (template.with [,as <slot>]
                 [(,as (its <slot> field))]

                 [[modifier.as_binary #modifier]
                  [//index.as_binary #name]
                  [//index.as_binary #descriptor]
                  [(binaryF.sequence_16 //attribute.as_binary) #attributes]]))
           )))

(the .public (field modifier name with_signature? type attributes)
  (-> (Modifier Field) UTF8 Bit (Type Value) (Sequence Attribute)
      (Resource Field))
  (monad.let [! //constant/pool.monad]
    [@name (//constant/pool.utf8 name)
     @descriptor (//constant/pool.descriptor (//type.descriptor type))
     @signature (if with_signature?
                    (by ! each (|>> {.#Some}) (//attribute.signature (//type.signature type)))
                    (pure {.#None}))]
    (pure [#modifier modifier
           #name @name
           #descriptor @descriptor
           #attributes (when @signature
                         {.#Some @signature}
                         (sequence.suffix @signature attributes)
                         
                         {.#None}
                         attributes)])))
