aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/target/jvm/attribute.lux
blob: 6d94c1b5bfc756e797725a1fc1510c0b8242ada8 (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
(.module:
  [library
   [lux (#- Info Code)
    [abstract
     [monad (#+ do)]
     ["." equivalence (#+ Equivalence)]]
    [control
     ["." try]
     ["." exception (#+ exception:)]]
    [data
     ["." sum]
     ["." product]
     [format
      [".F" binary (#+ Writer)]]]
    [math
     [number
      ["n" nat]]]]]
  ["." // #_
   ["#." index (#+ Index)]
   [encoding
    ["#." unsigned (#+ U2 U4)]]
   ["#." constant (#+ UTF8 Class Value)
    ["#/." pool (#+ Pool Resource)]]]
  ["." / #_
   ["#." constant (#+ Constant)]
   ["#." code]])

(type: #export (Info about)
  {#name (Index UTF8)
   #length U4
   #info about})

(def: #export (info_equivalence Equivalence<about>)
  (All [about]
    (-> (Equivalence about)
        (Equivalence (Info about))))
  ($_ product.equivalence
      //index.equivalence
      //unsigned.equivalence
      Equivalence<about>))

(def: (info_writer writer)
  (All [about]
    (-> (Writer about)
        (Writer (Info about))))
  (function (_ [name length info])
    (let [[nameS nameT] (//index.writer name)
          [lengthS lengthT] (//unsigned.writer/4 length)
          [infoS infoT] (writer info)]
      [($_ n.+ nameS lengthS infoS)
       (|>> nameT lengthT infoT)])))

(with_expansions [<Code> (as_is (/code.Code Attribute))]
  (type: #export #rec Attribute
    (#Constant (Info (Constant Any)))
    (#Code (Info <Code>)))

  (type: #export Code
    <Code>)
  )

(def: #export equivalence
  (Equivalence Attribute)
  (equivalence.rec
   (function (_ equivalence)
     ($_ sum.equivalence
         (info_equivalence /constant.equivalence)
         (info_equivalence (/code.equivalence equivalence))))))

(def: common_attribute_length
  ($_ n.+
      ## u2 attribute_name_index;
      //unsigned.bytes/2
      ## u4 attribute_length;
      //unsigned.bytes/4
      ))

(def: (length attribute)
  (-> Attribute Nat)
  (case attribute
    (^template [<tag>]
      [(<tag> [name length info])
       (|> length //unsigned.value (n.+ ..common_attribute_length))])
    ([#Constant] [#Code])))

## TODO: Inline ASAP
(def: (constant' @name index)
  (-> (Index UTF8) (Constant Any) Attribute)
  (#Constant {#name @name
              #length (|> /constant.length //unsigned.u4 try.assumed)
              #info index}))

(def: #export (constant index)
  (-> (Constant Any) (Resource Attribute))
  (do //constant/pool.monad
    [@name (//constant/pool.utf8 "ConstantValue")]
    (in (constant' @name index))))

## TODO: Inline ASAP
(def: (code' @name specification)
  (-> (Index UTF8) Code Attribute)
  (#Code {#name @name
          ## https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.3
          #length (|> specification
                      (/code.length ..length)
                      //unsigned.u4
                      try.assumed)
          #info specification}))

(def: #export (code specification)
  (-> Code (Resource Attribute))
  (do //constant/pool.monad
    [@name (//constant/pool.utf8 "Code")]
    (in (code' @name specification))))

(def: #export (writer value)
  (Writer Attribute)
  (case value
    (#Constant attribute)
    ((info_writer /constant.writer) attribute)
    
    (#Code attribute)
    ((info_writer (/code.writer writer)) attribute)))