aboutsummaryrefslogtreecommitdiff
path: root/new-luxc/source/luxc/lang/packager.lux
blob: f18055b189261e3d155bc7567fee5527b40529e1 (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
(.module:
  [lux #*
   ["." host (#+ import: do-to)]
   [data
    ["." binary (#+ Binary)]
    ["." text]
    [number
     ["n" nat]]
    [collection
     ["." row]
     ["." list ("#@." fold)]]]
   [target
    [jvm
     [encoding
      ["." name (#+ External)]]]]
   [tool
    [compiler
     [phase
      [generation (#+ Buffer Output)]]
     [meta
      [archive
       [descriptor (#+ Module)]]]]]]
  [//
   [host
    [jvm (#+ Definition)]]])

(import: #long java/lang/Object)

(import: #long java/lang/String)

(import: #long java/util/jar/Attributes
  (put [java/lang/Object java/lang/Object] #? java/lang/Object))

(import: #long java/util/jar/Attributes$Name
  (#static MAIN_CLASS java/util/jar/Attributes$Name)
  (#static MANIFEST_VERSION java/util/jar/Attributes$Name))

(import: #long java/util/jar/Manifest
  (new [])
  (getMainAttributes [] java/util/jar/Attributes))

(import: #long java/io/Flushable
  (flush [] void))

(import: #long java/io/Closeable
  (close [] void))

(import: #long java/io/OutputStream)

(import: #long java/io/ByteArrayOutputStream
  (new [int])
  (toByteArray [] [byte]))

(import: #long java/util/zip/ZipEntry)

(import: #long java/util/zip/ZipOutputStream
  (write [[byte] int int] void)
  (closeEntry [] void))

(import: #long java/util/jar/JarEntry
  (new [java/lang/String]))

(import: #long java/util/jar/JarOutputStream
  (new [java/io/OutputStream java/util/jar/Manifest])
  (putNextEntry [java/util/zip/ZipEntry] void))

(def: byte 1)
(def: kilo-byte (n.* 1,000 byte))
(def: mega-byte (n.* 1,000 kilo-byte))

(def: manifest-version "1.0")

(def: class-name
  (-> Text Text)
  (text.suffix ".class"))

(def: (manifest program-class)
  (-> External java/util/jar/Manifest)
  (let [manifest (java/util/jar/Manifest::new)]
    (exec (do-to (java/util/jar/Manifest::getMainAttributes manifest)
            (java/util/jar/Attributes::put (java/util/jar/Attributes$Name::MAIN_CLASS) program-class)
            (java/util/jar/Attributes::put (java/util/jar/Attributes$Name::MANIFEST_VERSION) ..manifest-version))
      manifest)))

(def: (write-class [def-name [class-name bytecode]] sink)
  (-> [Name Definition] java/util/jar/JarOutputStream java/util/jar/JarOutputStream)
  (let [class-name (|> class-name name.internal name.read ..class-name)]
    (do-to sink
      (java/util/jar/JarOutputStream::putNextEntry (java/util/jar/JarEntry::new class-name))
      (java/util/zip/ZipOutputStream::write bytecode +0 (.int (binary.size bytecode)))
      (java/io/Flushable::flush)
      (java/util/zip/ZipOutputStream::closeEntry))))

(def: (write-module [module classes] sink)
  (-> [Module (Buffer Definition)] java/util/jar/JarOutputStream java/util/jar/JarOutputStream)
  (|> classes
      row.to-list
      (list@fold ..write-class sink)))

(def: #export (package program-class outputs)
  (-> External (Output Definition) Binary)
  (let [buffer (java/io/ByteArrayOutputStream::new (.int mega-byte))
        sink (java/util/jar/JarOutputStream::new buffer (manifest program-class))]
    (exec (|> outputs
              row.to-list
              (list@fold ..write-module sink))
      (do-to sink
        (java/io/Flushable::flush)
        (java/io/Closeable::close))
      (java/io/ByteArrayOutputStream::toByteArray buffer))))